{"id":9341,"date":"2026-09-03T09:00:33","date_gmt":"2026-09-03T00:00:33","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=9341"},"modified":"2026-10-09T11:08:28","modified_gmt":"2026-10-09T02:08:28","slug":"nextjs-project-summary","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/09\/03\/nextjs-project-summary\/","title":{"rendered":"[nextjs]\ud504\ub85c\uc81d\ud2b8\uc694\uc57d\/project summary(myapp30+)"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc774 \ud504\ub85c\uc81d\ud2b8 \uc694\uc57d\uc740 myapp30\ubd80\ud130 \uc801\uc6a9\ub429\ub2c8\ub2e4.<br>This project summary applies starting from myapp30.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc804\uccb4 \ucf54\ub4dc\ub294 \uae43\ud5c8\ube0c\uc5d0\uc11c \ud655\uc778 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br>You can find the full code on GitHub.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/gideonslife01\/flm-nextjs\">https:\/\/github.com\/gideonslife01\/flm-nextjs<\/a><\/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\" style=\"font-size:14px\"><code>myapp project\/  \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 <strong>hooks\/useCursorPagination.ts    -&gt; Pagination Hook<\/strong>\n\u2502   \u251c\u2500\u2500 api\/follow\/route.ts    -&gt; Follow API(temporary)\n\u2502   \u251c\u2500\u2500 api\/announce\/route.ts  -&gt; Boost(Announcement)\n\u2502   \u251c\u2500\u2500 api\/like\/route.ts.     -&gt; Like API\n\u2502   \u251c\u2500\u2500 api\/posts\/route.ts     -&gt; Writing API(deprecated)\n\u2502   \u251c\u2500\u2500 api\/timeline\/route.ts  -&gt; Timeline API\n\u2502   \u251c\u2500\u2500 api\/followinglist\/route.ts  -&gt; followinglist API\n\u2502   \u251c\u2500\u2500 api\/followerslist\/route.ts  -&gt; followerslist API\n\u2502   \u251c\u2500\u2500 <span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">api\/v1\/instance<\/span>\/route.ts -&gt; auth\n\u2502   \u251c\u2500\u2500 api\/v1\/apps\/route.ts.    -&gt; auth\n\u2502   \u251c\u2500\u2500 api\/v1\/accounts\/verify_credentials\/route.ts -&gt; auth\n\u2502   \u251c\u2500\u2500 api\/v1\/statuses\/route.ts -&gt; Write Post\n\u2502   \u251c\u2500\u2500 <strong><span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">api\/v1\/timelines\/_home_back\/route.ts<\/span> -&gt; timeline(Depreacted)<\/strong>\n\u2502   \u251c\u2500\u2500 api\/v1\/media\/route.ts -&gt; Image upload\n\u2502   \u251c\u2500\u2500 api\/v1\/media\/&#91;id]\/route.ts  -&gt; Image Delete \n\u2502   \u251c\u2500\u2500 api\/v1\/instance\/rules\/route.ts -&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 api\/v1\/instance\/domain_blocks\/route.ts -&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 api\/v1\/filters\/route.ts -&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 api\/v1\/lists\/route.ts -&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 api\/v1\/announcements\/route.ts -&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 <strong>api\/v1\/timelines\/_public_back\/route.ts -&gt; Feature not implemented.(Deprecated)<\/strong>\n\u2502   \u251c\u2500\u2500 <strong>api\/v1\/timelines\/&#91;type]\/route.ts -&gt; Timeline API<\/strong>\n\u2502   \u251c\u2500\u2500 api\/v1\/statuses\/&#91;id]\/context\/route.ts -&gt; Post Check,Delete\n\u2502   \u251c\u2500\u2500 <span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">oauth\/authorize\/route.ts<\/span> -&gt; auth\n\u2502   \u251c\u2500\u2500 <span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">oauth\/token\/route.ts<\/span> -&gt; auth\n\u2502   \u251c\u2500\u2500 <span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">oauth\/login-and-authorize\/route.ts<\/span> -&gt; Tursky,Pinafore login processing\n\u2502   \u251c\u2500\u2500 oauth\/revoke\/route.ts -&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 <span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">api\/v1\/search\/home\/route.ts<\/span> -&gt; search\n\u2502   \u251c\u2500\u2500 <span style=\"background-color: initial; font-size: inherit; text-align: initial; color: initial;\">api\/v2\/search\/home\/route.ts<\/span> -&gt; search\n\u2502   \u251c\u2500\u2500 api\/v2\/notifications\/policy\/route.ts-&gt; Feature not implemented.\n\u2502   \u251c\u2500\u2500 api\/v1\/accounts\/&#91;id]\/followers\/route.ts -&gt; followers\n\u2502   \u251c\u2500\u2500 api\/v1\/accounts\/&#91;id]\/following\/route.ts -&gt; following\n\u2502   \u251c\u2500\u2500 api\/v1\/statuses\/&#91;id]\/route.ts -&gt; -&gt; Post delete(pinafore)\n\u2502   \u251c\u2500\u2500 api\/auth\/signup\/route.ts        -&gt; Website Signup\n\u2502   \u251c\u2500\u2500 api\/auth\/login\/route.ts         -&gt; Website Login\n\u2502   \u251c\u2500\u2500<strong> <\/strong>api\/auth\/logout\/route.ts        -&gt; Website Logout\n\u2502   \u251c\u2500\u2500<strong> <\/strong>api\/auth\/refresh\/route.ts       -&gt; Refresh Token\n\u2502   \u251c\u2500\u2500<strong> <\/strong>api\/cleanup-orphan\/route.ts     -&gt; post,outbox clean up\n\u2502   \u251c\u2500\u2500<strong> <\/strong>api\/auth\/me\/route.tsx           -&gt; Login Check<strong>\n<\/strong>\u2502   \u251c\u2500\u2500 auth\/signup\/page.tsx            -&gt; Signup UI\n\u2502   \u251c\u2500\u2500 auth\/signup\/page.tsx            -&gt; Login UI        \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]\/\n\u2502   \u2502   \u251c\u2500\u2500 page.tsx               -&gt; Timeline UI(Server, 404)\n\u2502   \u2502   \u251c\u2500\u2500 ClientPage.tsx.        -&gt; Timeline UI(Client,Call Active Themes)\n\u2502   \u2502   \u2514\u2500\u2500 _components\/themes\/\n\u2502   \u2502       \u251c\u2500\u2500 themeex\/ThemeexTheme.tsx      -&gt; Example Theme\n\u2502   \u2502       \u251c\u2500\u2500 themeex\/FollowersList.tsx     -&gt; Theme Example, FollowersList\n\u2502   \u2502       \u251c\u2500\u2500 themeex\/FollowingList.tsx     -&gt; Theme Example, FollowingList\n\u2502   \u2502       \u251c\u2500\u2500 themeex\/NotificationsList.tsx -&gt; Theme Example, NotificationsList\n\u2502   \u2502       \u251c\u2500\u2500 themeex\/TimelineList.tsx      -&gt; Theme Example, TimelineList\n\u2502   \u2502       \u251c\u2500\u2500 pinafore\/PinaforeTheme.tsx -&gt; Theme 1\n\u2502   \u2502       \u251c\u2500\u2500 pinafore\/FollowersList.tsx -&gt; Theme 1, FollowersList\n\u2502   \u2502       \u251c\u2500\u2500 pinafore\/FollowingList.tsx -&gt; Theme 1, FollowingList\n\u2502   \u2502       \u251c\u2500\u2500 pinafore\/NotificationsList.tsx -&gt; Theme 1, NotificationsList\n\u2502   \u2502       \u251c\u2500\u2500 pinafore\/TimelineList.tsx  -&gt; Theme 1, TimelineList\n\u2502   \u2502       \u251c\u2500\u2500 mastodon\/MastodonTheme.tsx -&gt; Theme 2\n\u2502   \u2502       \u2514\u2500\u2500 minimal\/MinimaltTheme.tsx  -&gt; Theme 3\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 theme.tsx              -&gt; Theme Provider\n\u2502   \u251c\u2500\u2500 watchThemes.ts         -&gt; Check real-time theme changes\n\u2502   \u251c\u2500\u2500 auth.ts                -&gt; Authentication, User Management\n\u2502   \u251c\u2500\u2500 ap.ts                  -&gt; Follow,Undo,Create,Likes,Announce\n\u2502   \u251c\u2500\u2500 visibility.ts          -&gt; Visibility(Public,Unlisted,Private,Direct)\n\u2502   \u2514\u2500\u2500 db.ts                  -&gt; DB connection\n\u251c\u2500\u2500 data\/\n\u2502   \u251c\u2500\u2500 keys\/userIDs\/          -&gt; private.pem, public.pem(New)\n\u2502   \u2514\u2500\u2500 keys\/                  -&gt; private.pem, public.pem(legacy)\n\u251c\u2500\u2500 data.sqlite                -&gt; Database(1\/3)\n\u251c\u2500\u2500 data.sqlite-wal            -&gt; Database(2\/3)\n\u251c\u2500\u2500 data.sqlite-shm            -&gt; Database(3\/3)\n\u251c\u2500\u2500 Caddyfile                  -&gt; https \n\u251c\u2500\u2500 instrumentation.ts         -&gt; Background Server\n\u251c\u2500\u2500 proxy.ts                   -&gt; middleware.ts - &gt;proxy.ts(for Nextjs16)\n\u251c\u2500\u2500 postcss.config.mjs         -&gt; for Nextjs16\n\u2514\u2500\u2500 package.json<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791(myapp)<br>Project Start (myapp)<\/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 ~\/myapp project\nnpm install better-sqlite3\nnpm install -D @types\/better-sqlite3<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 chokidar \uc124\uce58 \/ Installing chokidar<\/p>\n\n\n\n<p>&#8212; \uc2e4\uc2dc\uac04 \ud30c\uc77c \ubc0f \ud3f4\ub354\ubcc0\uacbd \uac10\uc2dc\uae30\ub2a5<br>Real-time file and folder change monitoring function<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install -D chokidar<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 bcrypt\uc124\uce58 \/ Installing bcrypt(myapp31+)<\/p>\n\n\n\n<p>&#8212; \ube44\ubc00\ubc88\ud638 \uc554\ud638\ud654 \/ Password encryption<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install bcrypt jsonwebtoken\nnpm install -D @types\/bcrypt @types\/jsonwebtoken<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 tailwindcss\/postcss \uc124\uce58 \/ Installing tailwindcss\/postcss<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>npm install -D @tailwindcss\/postcss\n# or\nnpm install -D tailwindcss @tailwindcss\/postcss<\/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=\"n5AaiRsxWD\"><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=Y7uyha8Jd2#?secret=n5AaiRsxWD\" data-secret=\"n5AaiRsxWD\" width=\"560\" height=\"315\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>\ud83d\udcc1 \ub3c4\uba54\uc778\ud5c8\uc6a9, @userid \uc0ac\uc6a9\ud558\uae30<br>Allowing domains, using @userid<\/p>\n\n\n\n<p>&#8212; next.config.ts<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n  \/* allow domain*\/\n  allowedDevOrigins: &#91;'aloy-horizon.duckdns.org', '*.duckdns.org'],\n\n  \/* host.domain.org\/@userid *\/\n<strong>  async rewrites() {\n    return &#91;\n      {\n        source: '\/@:username',\n        destination: '\/usersui\/:username',\n      },\n    ]\n  }<\/strong>\n};\n\n\nexport default nextConfig;\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1 myapp58 \uc774\uc804 \ucf54\ub4dc\uc5d0\uc11c middlware.ts\uac00 \uc788\ub294 \uacbd\uc6b0 proxy.ts\ub85c \ud30c\uc77c\uc774\ub984\uc744 \ubc14\uafb8\uace0 \ucf54\ub4dc\ub97c \uc544\ub798\uc640 \uac19\uc774 \uc218\uc815\ud569\ub2c8\ub2e4.(Nextjs16 \ubd80\ud130 proxy.ts\uc0ac\uc6a9\ud568)<br>If your existing myapp58 code contains a <code>middleware.ts<\/code> file, rename it to <code>proxy.ts<\/code> and modify the code as shown below (starting with Next.js 16, <code>proxy.ts<\/code> is used).<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code># middleware.ts\ud30c\uc77c\uc744 proxy.ts\ub85c \uc774\ub984\uc744 \ubc14\uafb8\uace0 \ucf54\ub4dc\ub97c \uc544\ub798\ucc98\ub7fc \uc218\uc815\n# Rename the `middleware.ts` file to `proxy.ts` and modify the code as shown below.\n\n\/\/export function middleware(req: NextRequest) {\n\n\/\/ \u2705 myapp58\nexport default function proxy(req: NextRequest) { ... ...}<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 Tailwind error<\/p>\n\n\n\n<p>\u2714\ufe0f Nextjs16\ubd80\ud130 \uc544\ub798\ucc98\ub7fc Tailwind \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc9c4\ud589\ud569\ub2c8\ub2e4.<br>Starting with Next.js 16, if a Tailwind error occurs as shown below, proceed as follows.<\/p>\n\n\n\n<p>\u2714\ufe0f \uc544\ub798\uc640 \uac19\uc740 \uc624\ub958 \ubc1c\uc0dd\uc2dc \ud504\ub85c\uc81d\ud2b8 \ub8e8\ud2b8\uc5d0 postcss.config.mjs \ud30c\uc77c\uc744 \ub9cc\ub4e4\uace0 \ucf54\ub4dc\ub97c \uc785\ub825\ud569\ub2c8\ub2e4.<br>If an error like the one below occurs, create a <code>postcss.config.mjs<\/code> file in the project root and enter the code.<\/p>\n\n\n\n<p>&#8212; Error<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>Unknown at rule: @theme\n\nGenerated code of PostCSS transform of file content of app\/globals.css:\n.\/app\/globals.css:8:7\n   6 | }\n   7 |\n&gt;  8 | @theme inline {\n     |       ^\n   9 |   --color-background: var(--background);\n  10 |   --color-foreground: var(--foreground);\n  11 |   --font-sans: var(--font-geist-sans);\n\nImport trace:\n  Client Component Browser:\n    .\/app\/globals.css &#91;Client Component Browser]\n    .\/app\/layout.tsx &#91;Server Component]\n<\/code><\/pre>\n\n\n\n<p>&#8212; \ucf54\ub4dc \/ Code<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code># postcss.config.mjs\nconst config = {\n  plugins: {\n    \"@tailwindcss\/postcss\": {},\n  },\n};\n\nexport default config;\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ubaa8\ub4c8\uc744 \ub2e4\uc2dc \uc124\uce58\ud569\ub2c8\ub2e4.<br>Reinstall the module.<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code>npm install -D @tailwindcss\/postcss\n# or\nnpm install -D tailwindcss @tailwindcss\/postcss<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \uacf5\uc2dd \ubb38\uc11c \/ Official Documentation (tailwindcss for nextjs)<\/p>\n\n\n\n<p><a href=\"https:\/\/tailwindcss.com\/docs\/installation\/framework-guides\/nextjs\">https:\/\/tailwindcss.com\/docs\/installation\/framework-guides\/nextjs<\/a><br><a href=\"https:\/\/www.npmjs.com\/package\/@tailwindcss\/postcss\">https:\/\/www.npmjs.com\/package\/@tailwindcss\/postcss<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1 \uc774\uc804 \ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c \uc2e0\uaddc \ud504\ub85c\uc81d\ud2b8\ub85c \ubcf5\uc0ac\ud560 \ud30c\uc77c<br>Files to copy from the previous project to the new project<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myapp project\/  \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\/                  -&gt; API\n\u2502   \u251c\u2500\u2500 users\/                -&gt; Inbox,Outbox,Post,Actor\n\u2502   \u251c\u2500\u2500 usersui\/              -&gt; Timeline UI,Theme\n\u2502   \u2514\u2500\u2500layout.tsx             -&gt; Privoder\n\u251c\u2500\u2500 public\/uploads.           -&gt; Image file upload(myapp50+)\n\u251c\u2500\u2500 lib\/\n\u251c\u2500\u2500 data\/                     -&gt; Key\n\u251c\u2500\u2500 .env.local                -&gt; Environment Variables\n\u251c\u2500\u2500 data.sqlite               -&gt; Database(WAL)\n\u251c\u2500\u2500 data.sqlite-wal           -&gt; Database(WAL)\n\u251c\u2500\u2500 data.sqlite-shm           -&gt; Database(WAL)\n\u251c\u2500\u2500 Caddyfile                 -&gt; https \n\u251c\u2500\u2500 next.config.ts            -&gt; DDNS,@\n\u251c\u2500\u2500 proxy.ts(middleware.ts)   -&gt; middleware(for Nextjs16)\n\u251c\u2500\u2500 postcss.config.mjs        -&gt; tailwindcss(for Nextjs16)\n\u2514\u2500\u2500 instrumentation.ts        -&gt; Background Server<\/code><\/pre>\n\n\n\n<p>1)\ub370\uc774\ud130\ubca0\uc774\uc2a4 \ud30c\uc77c\uc740 3\uac1c \ubaa8\ub450 \uc62e\uae41\ub2c8\ub2e4.<br>Move all three database files.<\/p>\n\n\n\n<p>2) \uc544\ub798\uc758 \uba85\ub839\uc744 \uc2e4\ud589\ud558\uba74 \ud30c\uc77c\uc744 data.sqlite\ud558\ub098\ub85c \ubcd1\ud569\ud558\uba74 data.sqlite\ud30c\uc77c\ud558\ub098\ub9cc \uc62e\uae38 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br>If you run the command below to merge the files into a single <code>data.sqlite<\/code> file, you only need to move that one file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sqlite3 data.sqlite \"PRAGMA wal_checkpoint(TRUNCATE);\"<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ud504\ub85c\uc81d\ud2b8 \uc2e4\ud589 \/ Project Execution<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm run dev<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1 \ub514\ub809\ud1a0\ub9ac \uad6c\uc870 \ubc0f \ud30c\uc77c \uc0c1\uc138 \uc124\uba85<br>Detailed Description of Directory Structure and Files<\/p>\n\n\n\n<p>\u2714\ufe0f app\/.well-known\/webfinger\/route.ts <\/p>\n\n\n\n<p>&#8211; \ub2e4\ub978\uc11c\ubc84\uc5d0\uc11c  \ub0b4 \uc11c\ubc84\ub97c \uac80\uc0c9 \/ Search for my server on another server<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- `acct:user1@aloy-horizon.duckdns.org` \uac80\uc0c9\ud558\uba74 \ub0b4 actor \uc8fc\uc18c \uc54c\ub824\uc90c\nSearching for `acct:user1@aloy-horizon.duckdns.org` returns my actor address.\n\n- Mastodon\uc5d0\uc11c `@user1@aloy-horizon.duckdns.org` \uac80\uc0c9\ud560 \ub54c \uc0ac\uc6a9\ud568.\nUse this when searching for `@user1@aloy-horizon.duckdns.org` on Mastodon.\n\n- \uc5c6\uc73c\uba74 \ub2e4\ub978 \uc11c\ubc84\uc5d0\uc11c \ub0b4 \uc11c\ubc84\ub97c \ubabb \ucc3e\uc74c.\nWithout it, other servers won't be able to find your server.\n\n- \ud14c\uc2a4\ud2b8\/Test: https:\/\/aloy-horizon.duckdns.org\/.well-known\/webfinger?resource=acct:user1@aloy-horizon.duckdns.org<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app<code>\/api\/follow\/route.ts<\/code>&nbsp;&#8211; \ub0b4\uac00 \ub2e4\ub978 \uc11c\ubc84 \ud314\ub85c\uc6b0 \/ I follow other servers.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- POST: \ud314\ub85c\uc6b0 \uc2dc\uc791 -&gt; sendFollow()\ud568\uc218\ub85c \uc0c1\ub300 inbox\uc5d0 Follow \uc804\uc1a1\nStart following -&gt; Send a follow request to the recipient's inbox using the sendFollow() function.\n\n- DELETE: \uc5b8\ud314\ub85c\uc6b0 -&gt; sendUndoFollow()\ud568\uc218\ub85c \uc0c1\ub300 inbox\ub85c Undo Follow \uc804\uc1a1\nUnfollow -&gt; Send an \"Undo Follow\" to the other party's inbox using the `sendUndoFollow()` function.<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app<code>\/api\/like\/route.ts<\/code>&nbsp;&#8211; \uc88b\uc544\uc694 \/ Likes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- POST: \uc88b\uc544\uc694\/Like -&gt; sendLike()\n- DELETE: \uc88b\uc544\uc694 \ucde8\uc18c\/Cancle Like -&gt; sendUndoLike()<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f<code>app\/api\/posts\/route.ts<\/code>&nbsp;&#8211; \uae00 \uc870\ud68c,\uc4f0\uae30,\uc218\uc815,\uc0ad\uc81c \/ View, write, edit, and delete posts<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- GET: \ub0b4 \uae00\ub9cc \uc870\ud68c\/View only my posts (SELECT * FROM posts WHERE username = ?)\n\n- POST: \uae00 \uc4f0\uae30 -&gt; DB \uc800\uc7a5 + followers\uc5d0\uac8c sendNote()\ub85c \ubc30\ub2ec! \nWrite a post -&gt; Save to DB + Deliver to followers via sendNote()\n\n- PUT: \uae00 \uc218\uc815 -&gt; DB\ub9cc \uc218\uc815 \nEdit post -&gt; Update DB only \n\n- DELETE: \uae00 \uc0ad\uc81c -&gt; DB \uc0ad\uc81c + followers\uc5d0\uac8c sendDelete()\ub85c \uc0ad\uc81c \uc804\ud30c\nDelete post -&gt; Delete from DB + propagate deletion to followers via sendDelete()<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app<code>\/api\/timeline\/route.ts<\/code>  &#8211; posts(outbox) + inxbox_posts(inbox) <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> - GET: posts(\ub0b4 \uae00) + inbox_posts(\ub0a8\uc774 \uc4f4 \uae00) \ucd5c\uc2e0\uc21c\uc73c\ub85c \ucd5c\uc2e0\uc21c\uc73c\ub85c \uac80\uc0c9\nSearch posts (my posts) + inbox_posts (posts by others) by recency.\n\n- \/usersui\/user1 \ud0c0\uc784\ub77c\uc778 UI\uac00 \uc774 API\ub97c \ud638\ucd9c\ud568\n\/usersui\/user1 The timeline UI calls this API.<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app<code>\/users\/[username]\/route.ts<\/code> &#8211; Actor \ud504\ub85c\ud544 \/ Actor Porfile<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- GET: \ub0b4 \ud504\ub85c\ud544 \uc815\ubcf4 (publicKey, inbox, outbox, followers, following URL \uc54c\ub824\uc90c)\nMy profile information (provides publicKey, inbox, outbox, followers, and following URLs)\n\n- \uc0c1\ub300 \uc11c\ubc84\uac00 \ub0b4 \uc11c\ubc84\ub97c \uc870\ud68c\ud560 \ub54c \uc0ac\uc6a9\ud568.\nUsed when a remote server queries my server.\n\n- \ud14c\uc2a4\ud2b8\/Test: https:\/\/aloy-horizon.duckdns.org\/users\/user1\n\n- \uc5c6\uc73c\uba74 \uc5f0\ubc29 \uc790\uccb4\uac00 \uc548 \ub428!\nWithout it, the federation itself cannot function!<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>app\/users\/[username]\/statuses\/[id]\/route.ts<\/code>&nbsp;&#8211; \uac1c\ubcc4 \uae00 \/ Individual Posts<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- GET: \uae00 1\uac1c \uc0c1\uc138\ubcf4\uae30 \/ View post details\n\n- \uc5ed\ud560\/Role: \n    1. posts \ud14c\uc774\ube14\uc5d0\uc11c \ub0b4 \uae00 \ucc3e\uae30\n       Find my posts in the 'posts' table\n    2. inbox_posts \ud14c\uc774\ube14\uc5d0\uc11c \ub0a8\uc758 \uae00 \ucc3e\uae30\n       Finding posts by others in the inbox_posts table\n    3. Note JSON\uc73c\ub85c \ubc18\ud658 (to, cc, content \ub4f1)\n       Note: Returned as JSON (to, cc, content, etc.)\n\n- \ud14c\uc2a4\ud2b8\/Test: \/users\/user1\/statuses\/e6c99652-572f-491a-9e61-05e67b0d58fc\n\n- \uc5c6\uc73c\uba74 Mastodon\uc5d0\uc11c \ub0b4 \uae00 \ud074\ub9ad\ud558\uba74 404\uc5d0\ub7ec \ubc1c\uc0dd\ud568.\nWithout it, clicking on my post in Mastodon results in a 404 error.<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app<code>\/users\/[username]\/following\/route.ts<\/code> <\/p>\n\n\n\n<p>&#8211; \ub0b4\uac00 \ud314\ub85c\uc6b0 \ud558\ub294 \uc0ac\ub78c \ubaa9\ub85d \/ List of people I follow<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET: \ub0b4\uac00 \ud314\ub85c\uc6b0\ud558\ub294 \uc0ac\ub78c\ub4e4 \ubaa9\ub85d\nList of people I follow<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>app\/users\/[username]\/inbox\/route.ts<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- POST: \uc0c1\ub300 \uc11c\ubc84\uc5d0\uc11c \uc624\ub294 \ubaa8\ub4e0 Activity \ubc1b\ub294 \uacf3\nEndpoint for receiving all activities from the remote server.\n\n    -- Follow \ubc1b\uc74c -&gt; following \ud14c\uc774\ube14 \ucd94\uac00 + sendAccept()\ub85c \uc218\ub77d\n       Upon receiving a follow request -&gt; Add to the 'following' table + accept via `sendAccept()`.\n\n    -- Accept \ubc1b\uc74c -&gt; followers \ud14c\uc774\ube14 \ucd94\uac00!\n       Accept received -&gt; Added to the 'followers' table!\n\n    -- Create(Note) \ubc1b\uc74c -&gt; inbox_posts \ud14c\uc774\ube14\uc5d0 \uc800\uc7a5(\ud0c0\uc784\ub77c\uc778\uc5d0 \ub738)\n       Receive Create(Note) -&gt; Save to `inbox_posts` table (appears on the timeline)\n\n    -- Like \ubc1b\uc74c -&gt; likes \ud14c\uc774\ube14 \uc800\uc7a5\n       \"Like\" received -&gt; Save to the 'likes' table\n\n    -- Announce(Boost) \ubc1b\uc74c -&gt; announces \ud14c\uc774\ube14 \uc800\uc7a5\n       'Announce(Boost)' received -&gt; Save to the 'announces' table!\n\n    -- Delete \ubc1b\uc74c -&gt; inbox_posts\uc5d0\uc11c \uc0ad\uc81c\n       Delete 'Received' -&gt; Delete from inbox_posts\n\n    -- Undo \ubc1b\uc74c -&gt; \ud574\ub2f9 \ub370\uc774\ud130 \uc0ad\uc81c\n       Undo received -&gt; Corresponding data deleted\n\n- ActivityPub \uc5f0\ubc29 \uc218\uc2e0\uc758 \ud575\uc2ec \/ The core of ActivityPub federal receiving<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/users\/[username]\/outbox\/route.ts<\/code> &#8211; \ub0b4\uac00 \uc4f4 \uae00 \ubaa9\ub85d \/ List of posts I&#8217;ve written<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- GET: \ub0b4 \uae00 \ubaa9\ub85d\uc744 ActivityPub \ud45c\uc900(OrderedCollection)\uc73c\ub85c \ubc18\ud658\nReturn the list of my posts in the ActivityPub standard (OrderedCollection) format.\n\n- POST : ActivityPub\ud45c\uc900 pinafore\ub4f1\uc5d0\uc11c \uae00 \uc791\uc131\ud560 \ub54c \uc0ac\uc6a9\nUsed when composing posts in ActivityPub-compliant applications such as Pinafore.\n\n- \/api\/posts\ub791 \ube44\uc2b7\ud558\uc9c0\ub9cc outbox\ub294 \ud45c\uc900 \ud3ec\ub9f7, \/api\/posts\ub294 \ub0b4 UI\uc6a9\nIt's similar to \/api\/posts, but outbox is the standard format, while \/api\/posts is for my UI.<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/usersui\/[username]\/page.tsx<\/code>&nbsp; &#8211; \ud0c0\uc784\ub77c\uc778 UI \/ Timeline UI<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c \ubcf4\ub294 \ud0c0\uc784\ub77c\uc778 \ud654\uba74(\ud14c\ub9c8\ub97c \ud30c\uc77c\uc744 \ubd88\ub7ec\uc634)\nTimeline view in the browser (loading the theme file)\n\n- \/api\/timeline \ud638\ucd9c\ud574\uc11c \uae00 \ubcf4\uc5ec\uc90c\nCalls \/api\/timeline to display posts.\n\n- themes\/ - Pinafore, Mastodon, Minimal \ud14c\ub9c8 3\uac1c\nthemes\/ - 3 themes: Pinafore, Mastodon, and Minimal<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app\/api\/v1\/accounts\/[id]\/followers\/route.ts &#8211; pinafore \ud314\ub85c\uc6cc \ub9ac\uc2a4\ud2b8 \/ Pinafore follower list<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;aloy-horizon.duckdns.org\/api\/v1\/accounts\/user1\/followers<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app\/api\/v1\/accounts\/[id]\/following\/route.ts &#8211; pinafore \ud314\ub85c\uc789 \ub9ac\uc2a4\ud2b8 \/ Pinafore following list<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;aloy-horizon.duckdns.org\/api\/v1\/accounts\/user1\/following<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app\/api\/v1\/timelines\/home\/route.ts &#8211; pinafore \ud648 \ud0c0\uc784\ub77c\uc778 \ub77c\uc6b0\ud2b8 \/ pinafore home timeline<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;aloy-horizon.duckdns.org\/api\/v1\/timelines\/home\/<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f app\/api\/v1\/notifications &#8211; pinafore \uc54c\ub9bc \ub77c\uc6b0\ud2b8 \/ Pinafore Notification route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;aloy-horizon.duckdns.org\/api\/v1\/notifications<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ud30c\uc77c \ucd94\uac00\ub41c\uac83 \ub098\uc911\uc5d0 \ub530\ub85c \ucd94\uac00 \uc608\uc815<br>I plan to add the attached files separately later.<\/p>\n\n\n\n<p>\u2714\ufe0f <code>lib\/ap.ts<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \uc911\uc694\ud568\uc218 \ubaa8\uc74c\nCollection of Important Functions\n\n- getPrivateKey(): username\ubcc4 \uac1c\uc778\ud0a4 \ub85c\ub4dc\ngetPrivateKey(): Load private key by username\n\n- signAndSend(): \ubaa8\ub4e0 Activity \uc11c\uba85 + \uc804\uc1a1\nsignAndSend(): Sign and send all activities.\n\n- sendFollow, sendAccept, sendNote, sendLike, sendAnnounce, sendDelete...\n<\/code><\/pre>\n\n\n\n<p>&#8212; lib\/ap.ts \uc804\uccb4 \ud568\uc218 \/ full function<\/p>\n\n\n\n<p>1)\uacf5\uc6a9\ud568\uc218 \/ Common function<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-regular\" style=\"font-size:14px\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud568\uc218 \/ Functions<\/th><th>\uae30\ub2a5 \/ Features<\/th><th>\uc0ac\uc6a9\ucc98 \/ Usage<\/th><\/tr><\/thead><tbody><tr><td><code>getPrivateKey(username)<\/code><\/td><td>&#8211; <code>username<\/code>\ubcc4 \uac1c\uc778\ud0a4 \ub85c\ub4dc<br><code>data\/keys\/{username}\/private.pem<\/code>&nbsp;\uc6b0\uc120<br>(Load private key by username<br>Prioritize )<br><code>data\/keys\/{username}\/private.pem<\/code>,<br><br>&#8211; \uc5c6\uc73c\uba74 (If there isn&#8217;t one)<br>&nbsp;<code>data\/keys\/private.pem<\/code>&nbsp;fallback<\/td><td><code>signAndSend<\/code>,&nbsp;<code>signedFetch<\/code>&nbsp;\uc11c\uba85\ud560 \ub54c<br>(When signing with signAndSend or signedFetch)<\/td><\/tr><tr><td><code>getPublicKey(username)<\/code><\/td><td>&#8211;<code>username<\/code>\ubcc4 \uacf5\uac1c\ud0a4 \ub85c\ub4dc<br>(Load public keys by username)<br><br><code>data\/keys\/{username}\/public.pemdata\/keys\/public.pem<\/code>&nbsp;(legacy)<code>data\/keys\/{username}.pub.pem<\/code>DB&nbsp;<code>users.public_key<\/code>&nbsp;fallback<\/td><td>Actor JSON \ub9cc\ub4e4 \ub54c, \ub0b4 \uacf5\uac1c\ud0a4 \ub178\ucd9c\ud560 \ub54c<br>(When creating an Actor JSON or exposing your public key)<\/td><\/tr><tr><td><code>signAndSend(inbox, doc, username)<\/code><\/td><td>Activity JSON \uc11c\uba85 (SHA-256 + RSA) + POST \uc804\uc1a1<br>\ubaa8\ub4e0&nbsp;<code>sendXXX<\/code>\uac00 \uc774\uac70 \uc0ac\uc6a9\ud568<br><code>Accept<\/code>,&nbsp;<code>Follow<\/code>,&nbsp;<code>Create<\/code>,&nbsp;<code>Like<\/code>,&nbsp;<code>Announce<\/code>&nbsp;\ub4f1<br><br>Activity JSON signing (SHA-256 + RSA) + POST transmission<br>Used by all <code>sendXXX<\/code> methods<br>Accept, Follow, Create, Like, Announce, etc.<\/td><td><code>sendAccept<\/code>,&nbsp;<code>sendCreate<\/code>,&nbsp;<code>sendLike<\/code>&nbsp;\ub4f1 \ubaa8\ub4e0 \ubc1c\uc1a1<br><br>All outgoing actions such as sendAccept, sendCreate, and sendLike<\/td><\/tr><tr><td><code>signedFetch(url, username)<\/code><\/td><td>GET \uc694\uccad\uc5d0 HTTP Signature \ubd99\uc5ec\uc11c \uac00\uc838\uc624\uae30<br>\uc0c1\ub300\ubc29 actor \uc815\ubcf4 \uc870\ud68c\ud560 \ub54c \uc0ac\uc6a9<br><br>Retrieving data by attaching an HTTP Signature to a GET request<br>Used when fetching information about a remote actor<\/td><td><code>fetchActorPublicKey<\/code>\uc5d0\uc11c Mastodon actor \uac00\uc838\uc62c \ub54c \ud544\uc218!<br><br>Essential when retrieving a Mastodon actor in <code>fetchActorPublicKey<\/code>!<\/td><\/tr><tr><td><code>verifyHttpSignature(req, publicKeyPem)<\/code><\/td><td>\uc0c1\ub300\ubc29\uc774 \ubcf4\ub0b8 HTTP Signature \uac80\uc99dSignature \ud5e4\ub354 \ud30c\uc2f1<code>signingString<\/code>&nbsp;\uc7ac\uad6c\uc131<br><code>(request-target) host date digest<\/code>\uacf5\uac1c\ud0a4\ub85c \uac80\uc99d<br><br>Verifying the HTTP Signature sent by the other party: parsing the Signature header, reconstructing the signingString, and verifying using the public key.<br>(request-target) host date digest<\/td><td><code>inbox\/route.ts<\/code>\uc5d0\uc11c \ubaa8\ub4e0 \uc694\uccad \uac80\uc99d!<br><br>Validate all requests in inbox\/route.ts!<\/td><\/tr><tr><td><code>fetchActorPublicKey(actorUrl, username)<\/code><\/td><td>Actor URL\uc5d0\uc11c publicKey \uac00\uc838\uc624\uae30<code>signedFetch<\/code>&nbsp;\uc2dc\ub3c4 (Mastodon \ud544\uc218!)\uc2e4\ud328 \uc2dc Plain fetch fallback<code>username<\/code>&nbsp;undefined\uba74&nbsp;<code>user1<\/code>&nbsp;fallback<br><br>Attempt <code>signedFetch<\/code> to retrieve the <code>publicKey<\/code> from the Actor URL (required for Mastodon); fall back to plain <code>fetch<\/code> on failure; fall back to <code>user1<\/code> if the username is <code>undefined<\/code>.<\/td><td><code>verifyHttpSignature<\/code>&nbsp;\uac80\uc99d \uc804\uc5d0 \ud0a4 \uac00\uc838\uc62c \ub54c<br><br>When retrieving the key before verifying the HTTP signature<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>2)Activity \uc804\uc6a9 \ud568\uc218 \/ Activity-specific function<\/p>\n\n\n\n<figure style=\"font-size:14px\" class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud568\uc218\/Functions<\/th><th>\uc804\uc1a1\/Transmission<\/th><th>\uc0ac\uc6a9\/Use<\/th><\/tr><\/thead><tbody><tr><td><code>sendAccept(toInbox, followActivity, username)<\/code><\/td><td><code>Accept<\/code><\/td><td>\ub2e4\ub978 \uc0ac\ub78c\uc774 \ub0a0 \ud314\ub85c\uc6b0\ud588\uc744 \ub54c, \ud314\ub85c\uc6b0 \uc218\ub77d<br>When someone follows me, accept the follow<\/td><\/tr><tr><td><code>sendNote(toInbox, note, username, postId, content)<\/code><\/td><td><code>Create<\/code>&nbsp;+&nbsp;<code>Note<\/code><\/td><td>\ub0b4\uac00 \uae00 \uc37c\uc744 \ub54c, \ud314\ub85c\uc6cc inbox\ub85c \uae00 \ubc30\ub2ec<br>When I write a post, it gets delivered to my followers&#8217; inboxes.<\/td><\/tr><tr><td><code>sendFollow(toInbox, targetActor, username)<\/code><\/td><td><code>Follow<\/code><\/td><td>\ub0b4\uac00 \ub2e4\ub978 \uc0ac\ub78c \ud314\ub85c\uc6b0\ud560 \ub54c<br>When I follow someone else<\/td><\/tr><tr><td><code>sendUndoFollow(targetActor, username)<\/code><\/td><td><code>Undo<\/code>&nbsp;+&nbsp;<code>Follow<\/code><\/td><td>\ub0b4\uac00 \uc5b8\ud314\ub85c\uc6b0\ud560 \ub54c<br>When I unfollow<\/td><\/tr><tr><td><code>sendLike(toInbox, postId, username)<\/code><\/td><td><code>Like<\/code><\/td><td>\ub0b4\uac00 \ub2e4\ub978 \uc0ac\ub78c \uae00 \uc88b\uc544\uc694\ud560 \ub54c<br>When I &#8216;like&#8217; someone else&#8217;s post<\/td><\/tr><tr><td><code>sendUndoLike(toInbox, likeId, postId, username)<\/code><\/td><td><code>Undo<\/code>&nbsp;+&nbsp;<code>Like<\/code><\/td><td>\uc88b\uc544\uc694 \ucde8\uc18c\ud560 \ub54c<br>When cancelling a &#8216;Like&#8217;<\/td><\/tr><tr><td><code>sendAnnounce(toInbox, postId, username)<\/code><\/td><td><code>Announce<\/code><\/td><td>\ubd80\uc2a4\ud2b8\/\ub9ac\ud3ec\uc2a4\ud2b8 \ud560 \ub54c<br>When boosting\/reposting<\/td><\/tr><tr><td><code>sendUndoAnnounce(toInbox, announceId, postId, username)<\/code><\/td><td><code>Undo<\/code>&nbsp;+&nbsp;<code>Announce<\/code><\/td><td>\ubd80\uc2a4\ud2b8 \ucde8\uc18c\ud560 \ub54c<br>When canceling the boost<\/td><\/tr><tr><td><code>sendDelete(toInbox, postId, username)<\/code><\/td><td><code>Delete<\/code><\/td><td>\ub0b4 \uae00 \uc0ad\uc81c\ud588\uc744 \ub54c \ud314\ub85c\uc6cc\ub4e4\uc5d0\uac8c \uc0ad\uc81c \uc804\ud30c(myapp30)<br>Notify followers when my post is deleted (myapp30)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>3) inbox \uc8fc\uc18c\ucd94\ucd9c \/ Extract email addresses from the inbox<\/p>\n\n\n\n<figure style=\"font-size:14px\" class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud568\uc218 \/ function<\/th><th>\uae30\ub2a5\/features<\/th><\/tr><\/thead><tbody><tr><td><code>getActorData(actorUrl, username)<\/code><\/td><td>\uc0c1\ub300\ubc29&nbsp;<code>https:\/\/mastodon.social\/users\/xxx<\/code>&nbsp;\uc815\ubcf4 \uac00\uc838\uc640\uc11c&nbsp;<code>inbox<\/code>&nbsp;\uc8fc\uc18c \ucd94\ucd9c<br>Retrieve information for the user at https:\/\/mastodon.social\/users\/xxx and extract the inbox address.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>4) \uacf5\uac1c \ud0a4 \uac00\uc838\uc624\uae30 \ubc0f \uce90\uc2f1<br>Public Key Fetching and Caching <\/p>\n\n\n\n<figure style=\"font-size:14px\" class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\ud568\uc218\/Functions<\/th><th>\uc804\uc1a1\/Transmission<\/th><th>\uc0ac\uc6a9\/Use<\/th><\/tr><\/thead><tbody><tr><td>fetchActorPublicKeyCached()<\/td><td> Inbox \uc804\uc6a9(\ubc1b\ub294 \ucabd \uac80\uc99d)<br>Inbox-only (recipient-side verification)<\/td><td>&#8211; \uce90\uc2dc\uc5d0\uc11c publicKey \uac00\uc838\uc624\uae30!&nbsp;<code>CACHE_TTL<\/code>&nbsp;\uc720\ud6a8\ud558\uba74&nbsp;<code>\u26a1\ufe0f Cache hit!<\/code>&nbsp;\uc989\uc2dc \ub9ac\ud134! \uc5c6\uac70\ub098 \ub9cc\ub8cc\uba74&nbsp;<code>\ud83d\udd11 No cache<\/code>&nbsp;-&gt;&nbsp;<code>fetchActorPublicKey()<\/code>\ub85c Mastodon\uc5d0\uc11c \uac00\uc838\uc640\uc11c&nbsp;<code>set<\/code>!<br><br>Retrieve the public key from the cache! If the CACHE_TTL is valid -&gt; \u26a1\ufe0f Cache hit! Return immediately! If missing or expired -&gt; \ud83d\udd11 No cache -&gt; fetch it from Mastodon via <code>fetchActorPublicKey()<\/code> and set it!<\/td><\/tr><tr><td>fetchActorPublicKeyWithRetry()<\/td><td>Inbox \uc804\uc6a9! (\ubc1b\ub294 \ucabd \uac80\uc99d  \uc7ac\uc2dc\ub3c4)<br>Inbox Only! (Retry recipient verification)<\/td><td>&#8211; Inbox \uac80\uc99d \uc804\uccb4 \ud750\ub984! 1.&nbsp;<code>Cached()<\/code>\ub85c \uba3c\uc800 \uac80\uc99d! 2.&nbsp;<code>verifyHttpSignature()<\/code>&nbsp;\uc2e4\ud328\ud558\uba74&nbsp;<code>\u26a0\ufe0f Cache failed<\/code>&nbsp;-&gt; \uce90\uc2dc&nbsp;<code>delete<\/code>! 3.&nbsp;<code>fresh fetch<\/code>! 4. \uc7ac\uac80\uc99d \uc131\uacf5\ud558\uba74 \uc7ac\uce90\uc2dc!<br><br>Inbox verification workflow! 1. Verify using <code>Cached()<\/code> first! 2. If <code>verifyHttpSignature()<\/code> fails \u26a0\ufe0f Cache failed -&gt; delete cache! 3. Fresh fetch! 4. Re-cache upon successful re-verification!<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u2714\ufe0f<code>lib\/db.ts<\/code> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc5f0\uacb0 ,\ud14c\uc774\ube14 \ubc0f \uc778\ub371\uc2a4 \ucd08\uae30\ud654\nDatabase connection, table and index initialization<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \ucee8\ud14d\uc2a4\ud2b8 \ud504\ub85c\ubc14\uc774\ub354 \uc801\uc6a9 \ubd80\ubd84<br>Implementation of the Context Provider<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myapp project\/\n\u251c\u2500\u2500 lib\/\n\u2502   \u251c\u2500\u2500 theme.tsx              -&gt; Theme Provider (Context)\n\u2502   \u251c\u2500\u2500 watchThemes.ts         -&gt; Check real-time theme changes\n\u2502   \u251c\u2500\u2500 ap.ts                  -&gt; Follow Accept\n\u2502   \u2514\u2500\u2500 db.ts                  -&gt; DB connection\n\u2514\u2500\u2500 app\/\n    \u251c\u2500\u2500 usersui\/&#91;username]\/\n    \u2502   \u251c\u2500\u2500 page.tsx           -&gt; Timeline UI (Use Provider)\n    \u2502   \u2514\u2500\u2500 _components\/themes\/\n    \u2514\u2500\u2500 layout.tsx             -&gt; Apply the provider to the project<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f<code>\/lib\/theme.tsx<\/code> &#8211; \ud14c\ub9c8 \ucee8\ud14d\uc2a4\ud2b8 \ud504\ub85c\ubc14\uc774\ub354 \/ Theme context provider<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \ud14c\ub9c8 \uc0c1\ud0dc \uc804\uc5ed \uc800\uc7a5\nGlobally store the theme state. (useContext)\n\n    - currentTheme\n      \/app\/usersui\/&#91;username]\/_components\/themes\/themeNames.tsx\n\n    - localStorage\uc5d0 \uc800\uc7a5\ud574\uc11c \uc0c8\ub85c\uace0\uce68\ud574\ub3c4 \ud14c\ub9c8 \uc720\uc9c0\n      Save to localStorage to maintain the theme even after refreshing.<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/lib\/watchThemes.ts<\/code>&nbsp;&#8211; \uc2e4\uc2dc\uac04 \ud14c\ub9c8 \uac10\uc9c0 \/ Real-time theme detection<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \ud14c\ub9c8\ub97c \uc11c\ubc84 \uc7ac\uc2dc\uc791 \uc5c6\uc774 \uc801\uc6a9\ud558\uae30 \uc704\ud574\uc11c \uc0ac\uc6a9\ud568.\nUsed to apply the theme without restarting the server.\n\n- \/app\/usersui\/&#91;username]\/_components\/themes\/ \ud3f4\ub354 \ud30c\uc77c \ubcc0\uacbd \uc2e4\uc2dc\uac04 \uac10\uc9c0\nReal-time detection of file changes in the \/app\/usersui\/&#91;username]\/_components\/themes\/ folder\n\n- chokidar\ub85c \ud30c\uc77c \ubcc0\uacbd \uac10\uc9c0\nDetect file changes with chokidar\n\n- instrumentation.ts\uc5d0\uc11c \ubc31\uadf8\ub77c\uc6b4\ub4dc\ub85c \uc2e4\ud589\nRun in the background in instrumentation.ts\n\n- app\/usersui\/&#91;username]\/ \ub514\ub809\ud1a0\ub9ac\ub0b4 index.ts \ubc0f themeNames.ts\ud30c\uc77c \uc0dd\uc131 \ubc0f \uc5c5\ub370\uc774\ud2b8\nCreate and update the index.ts and themeNames.ts files in the app\/usersui\/&#91;username]\/ directory.\n\n- index.ts \ubc0f themeNames.ts\ub294 usersui\/&#91;username]\/page.tsx\uc5d0\uc11c \ubd88\ub7ec\uc62c \ud14c\ub9c8\ud30c\uc77c \uacbd\ub85c\uac00 \uae30\ub85d\ub428.\n`index.ts` and `themeNames.ts` contain the file paths for the themes to be imported in `usersui\/&#91;username]\/page.tsx`.\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/app\/layout.tsx<\/code>&nbsp; &#8211; \ud504\ub85c\ubc14\uc774\ub354 \ub8e8\ud2b8 \/ Provider root<\/p>\n\n\n\n<p>&#8212; &lt;ThemeProvider&gt;\ub85c \uc804\uccb4 \uc571 \uac10\uc2f8\uc11c \ubaa8\ub4e0 \uacf3\uc5d0 theme\ubcc0\uc218 \uc801\uc6a9<br>Wrap the entire app with <code>&lt;ThemeProvider&gt;<\/code> to apply the theme variable everywhere.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { ThemeProvider } from \"@\/lib\/theme\"; \/\/ \u2705 myapp26\n... ...  \nreturn (\n    &lt;html\n      lang=\"en\"\n      className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}\n    &gt;\n      &lt;body className=\"min-h-full flex flex-col\"&gt;\n       <strong> &lt;ThemeProvider&gt;<\/strong>\n          {children}\n       <strong> &lt;\/ThemeProvider&gt;<\/strong>\n        &lt;\/body&gt;\n    &lt;\/html&gt;\n  );<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/app\/usersui\/[username]\/page.tsx<\/code> &#8211; \ud14c\ub9c8\ud638\ucd9c \ud398\uc774\uc9c0 \/ Theme Call Page<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \/api\/timeline \ud638\ucd9c\ud574\uc11c \uae00\ub3c4 \uac00\uc838\uc624\uace0, \ud14c\ub9c8\ub3c4 \uc801\uc6a9\nCall \/api\/timeline to fetch posts and apply the theme.\n\n- \ud504\ub85c\ubc14\uc774\ub354\uc5d0\uc11c \uc8fc\uc785\ub41c theme\ubcc0\uc218\ub85c \ud14c\ub9c8\ud30c\uc77c\uc744 \ubd88\ub7ec\uc635\ub2c8\ub2e4.\nLoad the theme file using the `theme` variable injected by the provider.\n\n- \ub610\ub294 pinafore\ub514\ub809\ud1a0\ub9ac\ub098 \uc790\ub3d9\uc0dd\uc131\ub41c index.ts\uc5d0\uc11c \ud14c\ub9c8\ud30c\uc77c\uc744 \ubd88\ub7ec\uc635\ub2c8\ub2e4.\nAlternatively, import the theme file from the `pinafore` directory or the automatically generated `index.ts`.\n\n\n- Code \n\n  const props = { timeline, username, onBoost: handleBoost, onLike: handleLike };\n  \n  \/\/ getThemeComponent : import { themeRegistry, getThemeComponent } from '.\/_components\/themes'; --&gt; index.ts\n<strong>  const ActiveTheme = getThemeComponent(theme as any) || themeRegistry.pinafore?.component || themeRegistry&#91;themeNames&#91;0]]?.component;<\/strong>\n  if (!ActiveTheme) return &lt;div&gt;No themes found&lt;\/div&gt;;\n\n  return <strong>&lt;ActiveTheme {...props} \/&gt;<\/strong>;<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/app\/usersui\/[username]\/_components\/themes\/<\/code> &#8211; \ud14c\ub9c8 \/ Theme<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- \ud14c\ub9c8 \ud30c\uc77c\uc774 \uc788\ub294 \ub514\ub809\ud1a0\ub9ac\nDirectory containing theme files\n\n1) themeex\/ThemeexTheme.tsx -&gt; Example Theme (\uc608\uc81c\/example)\n2) pinafore\/PinaforeTheme.tsx -&gt; Theme 1 (Pinafore Style)\n3) mastodon\/MastodonTheme.tsx -&gt; Theme 2 (Mastodon Style)\n4) minimal\/MinimaltTheme.tsx -&gt; Theme 3 (Minimal Style)<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/app\/usersui\/[username]\/_components\/themes\/<\/code>pinafore\/PinaforeTheme.tsx<\/p>\n\n\n\n<p>&#8212;  \ud14c\ub9c8\ud30c\uc77c \uc911 \ud558\ub098\uc785\ub2c8\ub2e4.<br>It is one of the theme files.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- select\uba54\ub274\uc5d0\uc11c \ud14c\ub9c8\ub97c \uc120\ud0dd\ud574\uc11c \ud14c\ub9c8 \ubcc0\uacbd\n1) select \uba54\ub274\uc5d0\uc11c \uba54\ub274\ub97c \uc120\ud0dd\n2) theme.tsx \ud30c\uc77c\uc5d0\uc11c \uc8fc\uc785\ub41c setTheme(newTheme); \ud568\uc218\uc2e4\ud589\n3) \ub85c\uceec\uc2a4\ud1a0\ub9ac\uc9c0\uc5d0 theme \uc774\ub984\uc744 \uc800\uc7a5\ud558\uace0 <\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f <code>\/instrumentation.ts<\/code> &#8211; \ubc31\uadf8\ub77c\uc6b4\ub4dc \uc11c\ubc84 \/ Background Server<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>- Next.js \uc11c\ubc84 \uc2dc\uc791 \uc2dc watchThemes.ts \uc2e4\ud589\nExecute watchThemes.ts when the Next.js server starts.<\/code><\/pre>\n\n\n\n<p>\ud83d\udcc1 \uc804\uccb4 \ub77c\uc6b0\ud2b8 \/ Full Route<\/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\n# 2. Actor (\ud504\ub85c\ud544 \/ Profile)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\n\n# 3. Followers (\ub0a8\uc774 \ub098 \ud314\ub85c\uc6b0 \/ Someone follows me)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/followers\n\n# 4. Following (\ub0b4\uac00 \ub0a8\uc744 \ud314\ub85c\uc6b0 \/ I follow others)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/following\n\n# 5. Outbox (\ub0b4 \uae00 \ubaa9\ub85d \/ My post list)\nhttps:\/\/aloy-horizon.duckdns.org\/users\/user1\/outbox\n\n# 6. \ud0c0\uc784\ub77c\uc778 \/ Timeline\n\n# - \ud0c0\uc784\ub77c\uc778UI \/ Timeline UI\nhttps:\/\/aloy-horizon.duckdns.org\/usersui\/user1\n# or\nhttps:\/\/aloy-horizon.duckdns.org\/@user1\n\n# - \ud0c0\uc784\ub77c\uc778API \/ Timeline API\nhttps:\/\/aloy-horizon.duckdns.org\/api\/timeline?username=user1\n\n# 7. \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\n# ex)\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<p>&#8212; \ud314\ub85c\uc6b0,\uc5b8\ud314\ub85c\uc6b0 \/ Follow,Unfollow<\/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\"}'<\/code><\/pre>\n\n\n\n<p>&#8212; \uae00 \uc4f0\uae30, \uae00 \uc218\uc815, \uae00 \uc0ad\uc81c<br>Write, Edit, Delete Post<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\ud83d\udca1  <strong>https:\/\/aloy-horizon.duckdns.org\/api\/posts \uc774 \ub77c\uc6b0\ud2b8\ub294 \uae30\ub2a5 \uc911\ubcf5\uc73c\ub85c \uc0ad\uc81c \ub420 \uc218 \uc788\uc74c\nThe route https:\/\/aloy-horizon.duckdns.org\/api\/posts may be removed due to functional redundancy.<\/strong>\n\n# \uae00 \uc4f0\uae30 - \ub85c\uceec (\ub85c\uceec \uc11c\ubc84 UI\uc804\uc6a9 ,outbox 7\ub85c \uc99d\uac00 + \ud314\ub85c\uc6cc\ub4e4\uc5d0\uac8c \ubc30\ub2ec)\n# Write Post - Local (Local server UI only; increment outbox to 7 + deliver 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 local UI #apiposts\"}'\n\n# \uae00\uc4f0\uae30 - ActivityPub \ud45c\uc900(pinafore\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \ub77c\uc6b0\ud2b8)\n# Writing - ActivityPub Standard (routes used in Pinafore)\n\n  curl -X POST https:\/\/aloy-horizon.duckdns.org\/users\/user1\/outbox \\\n  -H \"Content-Type: application\/activity+json\" \\\n  -d '{\"type\":\"Create\",\"object\":{\"content\":\"Hello Activity UI #activityposts \"}}'\n\n--- \n\n# myapp49\ubd80\ud130 ActivityPub  \uae00\uc4f0\uae30 \ub77c\uc6b0\ud2b8\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ncurl -s -X POST https:\/\/aloy-horizon.duckdns.org\/api\/v1\/statuses \\\n -H \"Cookie: <strong>refresh_token=099b61b8616edcf48b ... ...<\/strong>\" \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"status\":\"refresh token\",\"visibility\":\"public\"}'\n\n# myapp50\ubd80\ud130 \ub85c\uceec\uc11c\ubc84 \uae00\uc4f0\uae30 \ub77c\uc6b0\ud2b8\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/posts \\\n  -H \"Cookie: <strong>refresh_token=099b61b8616edcf48b4<\/strong>... ...\" \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"content\":\"token present\"}'\n\n---\n\n# \uae00 \uc218\uc815(\ub85c\uceec\ub9cc\uac00\ub2a5, \uad6c\ud604\uc608\uc815, \ub77c\uc6b0\ud2b8\uc788\uc74c)\n# Modify post (local-only, pending implementation, route exists)\n\ncurl -X PUT https:\/\/aloy-horizon.duckdns.org\/api\/posts \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"username\":\"user1\",\"id\":\"xxx\",\"content\":\"\uc218\uc815\ub41c \ub0b4\uc6a9\/Revised content\"}'\n\n# \u2757\ufe0f\uc5f0\ubc29 \uc218\uc815 \ucd94\uac00\ud558\ub824\uba74 \uc704 sendUpdate \ud568\uc218 \ucd94\uac00,\uc77c\ub2e8\uc740 \uae30\ub2a5 \ubcf4\ub958,\uc9c0\uc6d0\uc548\ub418\ub294 \uc11c\ubc84 \ub9ce\uc74c.\n# To add federal modifications, include the `sendUpdate` function mentioned above; however, this feature is currently on hold as many servers do not support it.\n# - lib\/ap.ts\uc5d0 sendUpdate \ud568\uc218\ucd94\uac00\n# Add the sendUpdate function to lib\/ap.ts.\n# - app\/api\/posts\/route.ts\uc758 PUT\ud568\uc218\uc5d0 sendUpdate\ud568\uc218 \ucd94\uac00\n# Add the `sendUpdate` function to the `PUT` function in`app\/api\/posts\/route.ts`.\n\n# \uae00 \uc0ad\uc81c  \/ Delete Posts(myapp30)\n\n# myapp30 \ubd80\ud130 GET\ubc29\uc2dd\ub3c4 \uc9c0\uc6d0\ud569\ub2c8\ub2e4.\n# 1) POST\n\ncurl -X DELETE https:\/\/aloy-horizon.duckdns.org\/api\/posts \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"username\":\"user1\",\"id\":\"e6c99652-572f-491a-9e61-05e67b0d58fc\"}'\n\n# ---\nmyapp49\ubd80\ud130 ActivityPub \uae00\uc0ad\uc81c \ub77c\uc6b0\ud2b8\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \nStarting with myapp49, the ActivityPub post deletion route has been modified as follows.\n\ncurl -s -X DELETE https:\/\/aloy-horizon.duckdns.org\/api\/v1\/statuses\/9a9f4c12-265c-46ed-b956-f51a5e61fdb2 \\\n -H \"Authorization: Bearer 099b61b8616edcf48b4cf7260ef818b7a451... ...\"\n\nmyapp50\ubd80\ud130 \ub85c\uceec\uc11c\ubc84 \uae00 \uc0ad\uc81c \ub77c\uc6b0\ud2b8\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.\nStarting with myapp50, the route for deleting posts on the local server has been modified as follows.\n\ncurl -s -X DELETE https:\/\/aloy-horizon.duckdns.org\/api\/posts \\\n -H \"Cookie: refresh_token=099b61b8616edcf48b4 ... ....\" \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"username\":\"user1\",\"id\":\"f0cba853-5fa3-4f28-bc44-6a367a78d0b3\"}'\n\n# ---\n\n# 2) GET\n\ncurl -X DELETE \"https:\/\/aloy-horizon.duckdns.org\/api\/posts?id=117204066261760455&amp;username=user1\"<\/code><\/pre>\n\n\n\n<p>\ud83d\udca1 \uc704\uc758 \ub77c\uc6b0\ud2b8\ub294<\/p>\n\n\n\n<p>&#8212; \uc88b\uc544\uc694 \uc2e4\ud589, \uc88b\uc544\uc694 \ucde8\uc18c  \/ Likes, Undo Likes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \uc88b\uc544\uc694 \uc2e4\ud589 \/ Likes\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/like \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"username\":\"user1\",\"target\":\"https:\/\/freelifemakers.com\/users\/user1\/statuses\/01M0XT1VBF23F8Y5EXAPK1VY56\"}'\n\n# \uc88b\uc544\uc694 \ucde8\uc18c\ud558\uae30 \/ Undo Likes\ncurl -X DELETE https:\/\/aloy-horizon.duckdns.org\/api\/like \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"username\":\"user1\",\"target\":\"https:\/\/mastodon.social\/@Gargron\/114559081070832514\"}'<\/code><\/pre>\n\n\n\n<p>&#8212; \ubd80\uc2a4\ud2b8 \uc2e4\ud589, \ubd80\uc2a4\ud2b8 \ucde8\uc18c \/ Boost, Cancle Boost<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n# \ubd80\uc2a4\ud2b8 \uc2e4\ud589 \/ Boost\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/announce \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"username\":\"user1\",\"target\":\"https:\/\/freelifemakers.com\/@user1\/statuses\/01M10AHFHCKGF9BY5G4H50VSHG\"}'\n\n# \ubd80\uc2a4\ud2b8 \ucde8\uc18c \/ Cancle Boost\ncurl -X DELETE https:\/\/aloy-horizon.duckdns.org\/api\/announce \\\n -H \"Content-Type: application\/json\" \\\n -d '{\"username\":\"user1\",\"target\":\"https:\/\/freelifemakers.com\/@user1\/statuses\/01M10AHFHCKGF9BY5G4H50VSHG\"}'<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \uc778\uc99d\uad00\ub828 \ub77c\uc6b0\ud2b8 \/ Authentication-related routes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n# pinafore \uc778\uc99d - pinafore\uac00 \uac00\uc838\uac08 \ub0b4 \uc11c\ubc84 \uc815\ubcf4\n# Pinafore Authorization \u2013 Server information accessed by Pinafore\ncurl https:\/\/aloy-horizon.duckdns.org\/api\/v1\/instance\n\n# pinafore \uc778\uc99d - \uc571\ub4f1\ub85d,pinafore\ub97c \uc571\uc73c\ub85c \ub0b4 \uc11c\ubc84\uc5d0 \ub4f1\ub85d\ud558\uae30\n# Pinafore Authentication \u2013 App Registration: Registering Pinafore as an App on My Server\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/v1\/apps \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\n    \"client_name\": \"Pinafore\",\n    \"redirect_uris\": \"urn:ietf:wg:oauth:2.0:oob\",\n    \"scopes\": \"read write follow push\",\n    \"website\": \"https:\/\/pinafore.social\"\n  }'\n\n# pinafore \uc778\uc99d -  Pinafore\uc5d0\uc11c \uc544\ub798\uc758 \ub77c\uc6b0\ud2b8 \uc2e4\ud589\ud574\uc11c \ube0c\ub77c\uc6b0\uc800 \uc2b9\uc778\ud654\uba74 \ud31d\uc5c5\n# Pinafore Authentication - Run the route below in Pinafore to open the browser approval screen popup\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/oauth\/token \\\n  -H \"Content-Type: application\/x-www-form-urlencoded\" \\\n  -d \"client_id=bdbaf975-d04b-4dc6-8525-6b94e9d09752&amp;client_secret=ee233e0e-a99f-4ca4-8487-09cce8219a1c4115f412-d65b-4268-944f-f0e6aed5199d&amp;code=df066428-3240-45cf-aa2a-6c4f809f875c&amp;grant_type=authorization_code&amp;redirect_uri=urn:ietf:wg:oauth:2.0:oob\"\n\n\n# pinafore \uc778\uc99d - Pinafore\uac00 \ubcf4\ub294 \ub0b4 \uc11c\ubc84\uc815\ubcf4,\ud0c0\uc784\ub77c\uc778\uc5d0 \ud45c\uc2dc\ub41c\ub294 \uc815\ubcf4\n# Pinafore Authorization \u2013 Server information accessed by Pinafore and information displayed on the timeline\ncurl https:\/\/aloy-horizon.duckdns.org\/api\/v1\/accounts\/verify_credentials \\\n  -H \"Authorization: Bearer 2f7f89d8-20e0-4e63-acac-5d3bea32deb11e323217-71b3-455a-8320-fc348e305611\"\n\n# pinafore \uc778\uc99d - \ub85c\uadf8\uc778 \ud6c4 \ud0c0\uc784\ub77c\uc778\n# Pinafore Authentication - Timeline after logging in \nhttps:&#47;&#47;aloy-horizon.duckdns.org\/v1\/timelines\/home\/route.ts\n\n# pinafore \uc778\uc99d - \ub85c\uadf8\uc778 \ud6c4 \ud0c0\uc784\ub77c\uc778\uc5d0 \ubcf4\uc774\ub294 \ub0b4\uac00 \uc791\uc131\ud55c\uae00\n# pinafore verification - Posts I've written that appear on the timeline after logging in.\nhttps:\/\/aloy-horizon.duckdns.org\/v1\/statuses\/route.ts\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \uac80\uc0c9\ub77c\uc6b0\ud2b8 \/ Search route<\/p>\n\n\n\n<p>&#8212; pinafore\uc5d0\uc11c \uc11c\ubc84 \uac80\uc0c9\ud560\ub54c \uc0ac\uc6a9<br>Used when searching for servers in pinafore<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud558\uc704 \ud638\ud658 \/ Backward compatibility\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/v1\/search?q=user1\" -H \"4847d5c9-efdd-450f-b724-01c28676d6ea433c1b89-a4ac-437b-a41a-39fc2e6bdfa6\"\n\n# \ud604\uc7ac \uc0ac\uc6a9\ub418\ub294 \ub77c\uc6b0\ud2b8 \/ Routes currently in use\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/v2\/search?q=user1\" -H \"4847d5c9-efdd-450f-b724-01c28676d6ea433c1b89-a4ac-437b-a41a-39fc2e6bdfa6\"<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f pinafore \ud314\ub85c\uc789,\ud314\ub85c\uc6b0 \ub77c\uc6b0\ud2b8<br>Pinafore Following\/Follow Route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># followers\napp\/api\/v1\/accounts\/&#91;id]\/followers\/route.ts\n\n# followiing\napp\/api\/v1\/accounts\/&#91;id]\/following\/route.ts<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f pinafore \ud648 \ud0c0\uc784\ub77c\uc778 \ub77c\uc6b0\ud2b8<br>Pinafore Home Timeline Route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl \"https:\/\/aloy-horizon.duckdns.org\/api\/v1\/timelines\/home\" \\\n  -H \"Authorization: Bearer YOUR_ACCESS_TOKEN\" | jq<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code># app\/api\/v1\/timelines\/home\/route.ts\n# Browser\nhttps:&#47;&#47;aloy-horizon.duckdns.org\/api\/v1\/timelines\/home\/\n\n# Terminal\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/v1\/timelines\/home\" \\\n  -H \"Authorization: Bearer 4847d5c9-efdd-450f-b724-01c28676d6ea433c1b89-a4ac-437b-a41a-39fc2e6bdfa6\" | jq\n\n# Terminal - limite 5\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/v1\/timelines\/home?limit=5\" \\\n  -H \"Authorization: Bearer 4847d5c9-efdd-450f-b724-01c28676d6ea433c1b89-a4ac-437b-a41a-39fc2e6bdfa6\" | jq<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f pinafore \uc54c\ub9bc \ub77c\uc6b0\ud2b8 (Pinafore\uac00 \uc0ac\uc6a9)<br>Pinafore notification route (used by Pinafore)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># app\/api\/v1\/notifications\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/v1\/notifications?limit=20\"<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Pinafore \uae00 \uc0ad\uc81c \ub77c\uc6b0\ud2b8<br>Pinafore Post deletion route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>api\/v1\/statuses\/&#91;id]\/route.ts<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Signup \ub77c\uc6b0\ud2b8 \/ Signup route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># api\/auth\/signup\/route.ts \ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/auth\/signup \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"username\":\"testuser\",\"email\":\"test@aloy-horizon.duckdns.org\",\"password\":\"12345678\"}' \\\n  -v<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Login \ub77c\uc6b0\ud2b8 \/ Login route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># api\/auth\/login\/route.ts\n# -c cookies.txt = \ubc1b\uc740! \ucfe0\ud0a4! \uc800\uc7a5!  -b cookies.txt = \uc800\uc7a5\ub41c! \ucfe0\ud0a4! \ubcf4\ub0b4\uae30!\n# -c cookies.txt = Save received cookies!  -b cookies.txt = Send saved cookies!\n\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/auth\/login \\\n  -H \"Content-Type: application\/json\" \\\n  -d '{\"email\":\"testuser\",\"password\":\"12345678\"}' \\\n  -c cookies.txt -b cookies.txt \\\n  -v\n\n# \uc131\uacf5 \ud558\uba74 \/ If you succeed\n# Set-Cookie: token=eyJhbG...; Path=\/; SameSite=Lax\n# {\"ok\":true,\"username\":\"testuser\",\"token\":\"eyJhbG...\"}\n\n# \ucfe0\ud0a4 \ud655\uc778 \/ Check Cookies\ncat cookies.txt<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Logout \ub77c\uc6b0\ud2b8 \/ Logout route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># api\/auth\/logout\/route.ts\n\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/auth\/logout \\\n  -b cookies.txt -c cookies.txt \\\n  -v\n\n# \ucfe0\ud0a4 \uc0ad\uc81c \ud655\uc778 \/ Confirm Cookie Deletion\ncat cookies.txt\n\n# \ub85c\uadf8\uc544\uc6c3 \ud6c4 authorize \ub2e4\uc2dc\ud558\uba74 \ub85c\uadf8\uc778\uc73c\ub85c \uc774\ub3d9\n# After logging out, re-authorizing redirects you to the login page.\n\ncurl -I \"https:\/\/aloy-horizon.duckdns.org\/oauth\/authorize?client_id=test\" \\\n  -b cookies.txt \\\n  -v\n\n# Location: \/auth\/login?next=... \ub098\uc624\uba74 \ub85c\uadf8\uc544\uc6c3 \uc131\uacf5!\n# If # Location: \/auth\/login?next=... appears, logout was successful!<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ub85c\uadf8\uc778 \ud655\uc778 \ub77c\uc6b0\ud2b8 \/ Login verification route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app\/api\/auth\/me\/route.tsx <\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ub9ac\ud504\ub808\uc2dc\ud1a0\ud070 \uac31\uc2e0 \ub77c\uc6b0\ud2b8 \/ Refresh token renewal route<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app\/api\/auth\/refresh\/route.ts  <\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ud314\ub85c\uc6cc \ubc0f \ud314\ub85c\uc789 \ub9ac\uc2a4\ud2b8 \ub77c\uc6b0\ud2b8 \/ Followers and Following List Routes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>app\/api\/followlist\/route.ts\napp\/api\/followinglist\/route.ts <\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f cleanup-orphan \ub77c\uc6b0\ud2b8 \/ route<\/p>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code># \ud1a0\ud070 \uba3c\uc800 \ud655\uc778 (\ube0c\ub77c\uc6b0\uc800 \uac1c\ubc1c\uc790\ub3c4\uad6c &gt; Application &gt; LocalStorage &gt; refresh_token)\n# \nexport TOKEN=\"your_refresh_token\"\n\n# 1. \uc804\uccb4 \uc0ad\uc81c \uc815\ubcf4\ud655\uc778 \/ Check Bulk Deletion Information (GET)\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# \ub2e8\uc77c \uae00 \uc0c1\ud0dc \ud655\uc778 \/ Check single post status\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?id=5a24536b-06ec-400c-8539-4c1350dd1d19\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# 2. \uc720\ub839\uae00 + 24\uc2dc\uac04 \uc9c0\ub09c \ubbf8\ub514\uc5b4 \uace0\uc544\ub9cc \uc0ad\uc81c \/ Delete only \"ghost posts\" and media items older than 24 hours.(POST)\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan \\\n  -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application\/json\"\n\n# \uc751\ub2f5 \uc608 \/ Response Example: \n{\"orphans\":3,\"deleted\":&#91;...],\"deletedFiles\":2,\"orphanMediasCleaned\":2}\n\n# 3. \ub9ac\ubaa8\ud2b8 + \ub85c\uceec + \ubbf8\ub514\uc5b4 \uc804\uccb4 \uc0ad\uc81c \/ Delete all remote, local, and media files (DELETE all)\ncurl -X DELETE \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?all=true\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# 4. \ub9ac\ubaa8\ud2b8 + \ub85c\uceec \ub2e8\uc77c \uae00 \uc0ad\uc81c \/ Delete single post (remote + local)(DELETE id)\ncurl -X DELETE \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?id=5a24536b-06ec-400c-8539-4c1350dd1d19\" \\\n  -H \"Authorization: Bearer $TOKEN\"\n\n# \uc751\ub2f5 \uc608 \/ Response Example: \n# {\"message\":\"\u2705 5a24536b... \ub9ac\ubaa8\ud2b8+\ub85c\uceec \uc0ad\uc81c \uc644\ub8cc \/ Remote and local deletion complete.\ub8cc!\",\"deletedId\":\"5a24536b...\",\"deletedFiles\":2,...}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:14px\"><code># \ud83d\udca1 \uc774 \ubd80\ubd84\uc740 \ub354\uc774\uc0c1 \uc0ac\uc6a9\ud558\uc9c0\uc54a\uc2b5\ub2c8\ub2e4.\n# 1. \uc804\uccb4 \uc0ad\uc81c \uc815\ubcf4\ud655\uc778 (GET)\n# Check Bulk Deletion Information (GET)\nCheck Bulk Deletion Information (GET)\n\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?username=user1\"\n\n# \ud130\ubbf8\ub110\uc5d0\uc11c \uc2e4\ud589 \uc608 \/ Example run in terminal\ncurl \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?id=5a24536b-06ec-400c-8539-4c1350dd1d19&amp;username=user1\"\n\n# 2. \uc720\ub839\uae00\ub9cc \uc0ad\uc81c (posts\uc640 outbox \ubd88\uc77c\uce58 \ud558\ub294 \uacbd\uc6b0)\n# Delete only \"ghost posts\" (cases where there is a mismatch between `posts` and `outbox`)\n\ncurl -X POST https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan \\\n  -H \"Content-Type: application\/json\" \n  -d '{\"username\":\"user1\"}'\n\n# 3. \ub9ac\ubaa8\ud2b8(GoToSocial, Mastodon) + \ub85c\uceec \uc804\uccb4 \uc0ad\uc81c \n# Delete all remote (GoToSocial, Mastodon) + local data\n\ncurl -X DELETE \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?username=user1&amp;all=true\"\n\n# \ub9ac\ubaa8\ud2b8 + \ub85c\uceec \uae00 \uc9c1\uc811\uc0ad\uc81c \/ Directly delete remote + local posts\ncurl -X DELETE \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?id=5a24536b-06ec-400c-8539-4c1350dd1d19&amp;username=user1\"\n\n# - \ud130\ubbf8\ub110\uc5d0\uc11c \uc2e4\ud589 \/ Run in the terminal\ncurl -X DELETE \"https:\/\/aloy-horizon.duckdns.org\/api\/cleanup-orphan?id=5a24536b-06ec-400c-8539-4c1350dd1d19&amp;username=user1\"\n\n# - \uc751\ub2f5 \/ Response\n{\"message\":\"\u2705 5a24536b-06ec-400c-8539-4c1350dd1d19 \ub9ac\ubaa8\ud2b8+\ub85c\uceec \uc0ad\uc81c \uc644\ub8cc! \uc774\uc81c 410 Tombstone!\",\"deletedId\":\"5a24536b-06ec-400c-8539-4c1350dd1d19\",\"tombstoneUrl\":\"https:\/\/aloy-horizon.duckdns.org\/users\/user1\/statuses\/5a24536b-06ec-400c-8539-4c1350dd1d19\",\"followersCount\":2}                             \n\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \uc774\ubbf8\uc9c0 \uc5c5\ub85c\ub4dc \ub77c\uc6b0\ud2b8<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud130\ubbf8\ub110 \ud14c\uc2a4\ud2b8 \uae08\uc9c0 \/ Terminal testing prohibited\napi\/v1\/media\/route.ts<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>\ud83d\udcc1 \uad00\ub828 \ubb38\uc11c \/ Related Documents<\/p>\n\n\n\n<p>\u2714\ufe0f 1. \uacf5\uc2dd \uc2a4\ud399 (W3C)&nbsp;<br>Official Specification (W3C)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;www.w3.org\/TR\/activitypub\/\nhttps:\/\/www.w3.org\/TR\/activitystreams-vocabulary\/<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f2.Mastodon \ubb38\uc11c! (\uc2e4\uc9c8\uc801 \ud45c\uc900)<br>Mastodon Documentation! (De facto standard)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;docs.joinmastodon.org\/spec\/activitypub\/<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f3. Fediverse \uac1c\ubc1c\uc790 \uc704\ud0a4 &#8211; \ud638\ud658\uc131 \uc815\ubcf4<br>Fediverse Developer Wiki &#8211; Compatibility Information<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;codeberg.org\/fediverse\/fep<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Mastodon \uc18c\uc2a4!(\ub8e8\ube44\ucf54\ub4dc)<br>Mastodon source code! (Ruby code)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;github.com\/mastodon\/mastodon\/blob\/main\/app\/lib\/activitypub\/activity\/update.rb<\/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\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \uc774 \ud504\ub85c\uc81d\ud2b8 \uc694\uc57d\uc740 myapp30\ubd80\ud130 \uc801\uc6a9\ub429\ub2c8\ub2e4.This project summary applies starting from myapp30. \ud83d\udc49\ud83c\udffb \uc804\uccb4 \ucf54\ub4dc\ub294 \uae43\ud5c8\ube0c\uc5d0\uc11c \ud655\uc778 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.You can find the full code on GitHub. https:\/\/github.com\/gideonslife01\/flm-nextjs \ud83d\udcc1 \uc804\uccb4 \ud504\ub85c\uc81d\ud2b8 \uad6c\uc870 \/ Overall Project Structure \ud83d\udcc1 \ud504\ub85c\uc81d\ud2b8 \uc2dc\uc791(myapp)Project Start (myapp) \ud83d\udcc1 SQLite\uc124\uce58 \/ Installing SQLite \ud83d\udcc1 chokidar \uc124\uce58 \/ Installing chokidar &#8212; \uc2e4\uc2dc\uac04 \ud30c\uc77c [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":10357,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,27,1,7],"tags":[],"class_list":["post-9341","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news","category-nextjs","category-uncategorized","category-website","has-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/9341","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=9341"}],"version-history":[{"count":124,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/9341\/revisions"}],"predecessor-version":[{"id":11908,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/9341\/revisions\/11908"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media\/10357"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=9341"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=9341"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=9341"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}