[nextjs]SNS Server-17(myapp27)

πŸ‘‰πŸ» myapp27μ—λŠ” μŠ€ν‚¨ 디렉토리 μ‹€μ‹œκ°„ μžλ™μΈμ‹μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€.
Real-time automatic detection of the skin directory is implemented in myapp27.

πŸ‘‰πŸ» 디렉토리λ₯Ό mv λͺ…λ Ήμ–΄λ‘œ μ΄λ™ν• κ²½μš° 였λ₯˜ λ‘œκ·Έκ°€ 좜λ ₯될 수 μžˆμŠ΅λ‹ˆλ‹€.
An error log may be displayed when moving a directory using the mv command.

πŸ‘‰πŸ» ν•˜μ§€λ§Œ 1μ΄ˆλ‚΄ λ°”λ‘œ 볡ꡬ μ™„λ£Œ λ©λ‹ˆλ‹€.
However, recovery is completed within one second.

πŸ‘‰πŸ» 전체 μ½”λ“œλŠ” κΉƒν—ˆλΈŒμ—μ„œ 확인 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
You can find the full code on GitHub.

https://github.com/gideonslife01/flm-nextjs

πŸ“ 전체 ν”„λ‘œμ νŠΈ ꡬ쑰 / Overall Project Structure

myapp26/  
β”œβ”€β”€ app/  (Next.js App Router)
β”‚   β”œβ”€β”€ .well-known/webfinger/route.ts  -> webfinger
β”‚   β”œβ”€β”€ api/follow/route.ts    -> Follow API(temporary)
β”‚   β”œβ”€β”€ api/announce/route.ts  -> Boost(Announcement)
β”‚   β”œβ”€β”€ api/like/route.ts.     -> Like API
β”‚   β”œβ”€β”€ api/posts/route.ts     -> Writing API
β”‚   β”œβ”€β”€ api/timeline/route.ts  -> Timeline API
β”‚   β”œβ”€β”€ users/[username]/
β”‚   β”‚   β”œβ”€β”€ statuses/[id]/route.ts -> Indivisual Post
β”‚   β”‚   β”œβ”€β”€ route.ts               -> Acotr Information
β”‚   β”‚   β”œβ”€β”€ followers/route.ts     -> Followers List
β”‚   β”‚   β”œβ”€β”€ following/route.ts     -> Following List
β”‚   β”‚   β”œβ”€β”€ inbox/route.ts         -> Inbox
β”‚   β”‚   └── outbox/route.ts        -> outbox
β”‚   β”œβ”€β”€ usersui/[username]/
β”‚   β”‚   β”œβ”€β”€ page.tsx               -> Timeline UI
β”‚   β”‚   └── _components/themes/
β”‚   β”‚       β”œβ”€β”€ themeex/ThemeexTheme.tsx   -> Example Theme
β”‚   β”‚       β”œβ”€β”€ pinafore/PinaforeTheme.tsx -> Theme 1
β”‚   β”‚       β”œβ”€β”€ mastodon/MastodonTheme.tsx -> Theme 2
β”‚   β”‚       └── minimal/MinimaltTheme.tsx  -> Theme 3
β”‚   β”œβ”€β”€ layout.tsx, page.tsx, globals.css
β”‚   └── favicon.ico
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ theme.tsx              -> Theme Provider
β”‚   β”œβ”€β”€ watchThemes.ts         -> Check real-time theme changes
β”‚   β”œβ”€β”€ ap.ts                  -> Follow Accept
β”‚   └── db.ts                  -> DB connection
β”œβ”€β”€ data/
β”‚   └── keys/                  -> private.pem, public.pem
β”œβ”€β”€ data.sqlite                -> Database
β”œβ”€β”€ Caddyfile                  -> https 
β”œβ”€β”€ instrumentation.ts         -> Background Server
└── package.json

πŸ“ ν”„λ‘œμ νŠΈ μ‹œμž‘(myapp27)
Project Start (myapp27)

npx create-next-app@latest

πŸ“ SQLiteμ„€μΉ˜ / Installing SQLite

cd ~/myapp27
npm install better-sqlite3
npm install -D @types/better-sqlite3

πŸ“ DDNS,httpsμ„€μ • / DDNS,https settings

πŸ“ λ„λ©”μΈν—ˆμš©, @userid μ‚¬μš©ν•˜κΈ°
Allowing domains, using @userid

— next.config.ts

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* allow domain*/
  allowedDevOrigins: ['aloy-horizon.duckdns.org', '*.duckdns.org'],

  /* host.domain.org/@userid */
  async rewrites() {
    return [
      {
        source: '/@:username',
        destination: '/usersui/:username',
      },
    ]
  }
};


export default nextConfig;

πŸ“ ν…Œλ§ˆ 디렉토리 μ‹€μ‹œκ°„ μžλ™μΈμ‹
Real-time automatic detection of theme directories

βœ”οΈ λͺ¨λ“ˆμ„€μΉ˜ / module installation

— μ‹€μ‹œκ°„ 파일 및 폴더변경 κ°μ‹œκΈ°λŠ₯
Real-time file and folder change monitoring function

npm install -D chokidar

πŸ“ μ½”λ“œ μˆ˜μ • 및 파일 생성
Code modification and file creation

βœ”οΈ myapp27/lib/watchTheme.ts -> 파일 생성 / Create file

— μ‹€μ‹œκ°„ 폴더 및 νŒŒμΌλ³€κ²½μ„ κ°μ§€ν•©λ‹ˆλ‹€.
It detects real-time changes to folders and files.

— _components디렉토리내에 index.ts,themeNames.tsνŒŒμΌμ„ μƒμ„±ν•˜κ³  μˆ˜μ •ν•©λ‹ˆλ‹€.
Create and modify the index.ts and themeNames.ts files within the _components directory.

import fs from 'fs';
import path from 'path';
import chokidar from 'chokidar';

let started = false;

export function watchThemes() { 
... ...
}

1)이 νŒŒμΌμ—μ„œ ν•΄λ‹Ή λ””λ ‰ν† λ¦¬λ‚΄μ˜ νŒŒμΌμ΄λ‚˜ 디렉토리 변경이 있으면 ν…Œλ§ˆνŒŒμΌ(index.ts,themeNames.ts)을 μ—…λ°μ΄νŠΈ ν•©λ‹ˆλ‹€.
This file updates the theme files (index.ts, themeNames.ts) whenever there are changes to files or directories within the specified directory.

2)index.ts,themeNames.ts파일이 μ—†μœΌλ©΄ μžλ™μƒμ„±ν•©λ‹ˆλ‹€.
If the index.ts and themeNames.ts files do not exist, they are automatically generated.

3)파일의 λ‚΄μš©μ΄λ‚˜ 디렉토리가 λ³€κ²½λ˜λ©΄ κ°μ§€ν•˜κ³  index.ts,themeNames.ts파일의 λ‚΄μš©μ„ μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€.
It detects changes to file contents or directories and updates the contents of index.ts and themeNames.ts.

βœ”οΈ myapp27/instrumentation.ts -> 파일 생성 / Create file

— Nextjs의 κΈ°λŠ₯으둜 watchTheme.tsλ₯Ό λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ‹€ν–‰ν•˜λ„λ‘ν•©λ‹ˆλ‹€.
Use Next.js features to run watchTheme.ts in the background.

// βœ… myapp27/instrumentation.ts - Next.js μ‹œμž‘ μ‹œ μžλ™ μ‹€ν–‰  / Automatic execution upon Next.js startup
export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    const { watchThemes } = await import('./lib/watchThemes');
    // λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 쑰용히 κ°μ‹œ μ‹œμž‘ / Start monitoring quietly in the background.
    watchThemes(); 
    console.log('πŸ‘€ Theme watcher started in background');
  }
}

βœ”οΈapp/usersui/[username]/_components/themes/page.tsx -> μˆ˜μ • / modify

— 이 νŒŒμΌμ—μ„œ 각 ν…Œλ§ˆλ””λ ‰ν† λ¦¬μ˜ νŒŒμΌμ„ 뢈러 μ˜΅λ‹ˆλ‹€.
This file loads the files from each theme directory.

— themeλ””λ ‰ν† λ¦¬μ˜ ν…Œλ§ˆλ₯Ό μžλ™μœΌλ‘œ λΆˆλŸ¬μ˜€λ„λ‘ μ½”λ“œ λ³€κ²½ν–ˆμŠ΅λ‹ˆλ‹€.
I modified the code to automatically load the theme from the theme directory.

//βœ… myappp27
import { themeRegistry, getThemeComponent } from './_components/themes'; // βœ… registry만 μ—¬κΈ°μ„œ κ°€μ Έμ˜€κΈ° / Import only the registry from here.
import { themeNames } from './_components/themes/themeNames'; // βœ… namesλŠ” λΆ„λ¦¬λœ νŒŒμΌμ—μ„œ κ°€μ Έμ˜€κΈ° / names are imported from a separate file

... ...

  if (loading) return <div style={{ padding: 20 }}>Loading...</div>;

  const props = { timeline, username, onBoost: handleBoost, onLike: handleLike };

  // ν…Œλ§ˆ μžλ™λΆ„κΈ°λ‘œ λ³€κ²½ / Changed to automatic theme switching.
  const ActiveTheme = getThemeComponent(theme as any) || themeRegistry.pinafore?.component || themeRegistry[themeNames[0]]?.component;

  if (!ActiveTheme) return <div>No themes found</div>;

  return <ActiveTheme {...props} />;

βœ”οΈ app/usersui/[username]/_components/themes/index.js

— 이 νŒŒμΌμ€ λ§Œλ“€μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€. μžλ™μƒμ„±λ©λ‹ˆλ‹€.
You do not need to create this file; it is generated automatically.

import { MastodonTheme } from './mastodon/MastodonTheme';
import { MinimalTheme } from './minimal/MinimalTheme';
import { PinaforeTheme } from './pinafore/PinaforeTheme';
import { ThemeexTheme } from './themeex/ThemeexTheme';

export const themeRegistry = {
 mastodon: { component: MastodonTheme, label: 'mastodon' },
 minimal: { component: MinimalTheme, label: 'minimal' },
 pinafore: { component: PinaforeTheme, label: 'pinafore' },
 themeex: { component: ThemeexTheme, label: 'themeex' },
} as const;
export type ThemeName = keyof typeof themeRegistry;
export function getThemeComponent(name: ThemeName) {
  return themeRegistry[name]?.component;
}

βœ”οΈ app/usersui/[username]/_components/themes/themeNames.ts

— 이 νŒŒμΌμ€ λ§Œλ“€μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€. μžλ™μƒμ„±λ©λ‹ˆλ‹€.
You do not need to create this file; it is generated automatically.

export const themeNames = ["mastodon","minimal","pinafore","themeex"] as const;
export type ThemeName = typeof themeNames[number];

βœ”οΈ app/usersui/[username]/_components/themes/pinafore/PinaforeTheme.tsx -> 파일 μˆ˜μ • / Modify file

— λ‹€λ₯Έ ν…Œλ§ˆνŒŒμΌμ€ μˆ˜μ •ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. myapp26의 λ‚΄μš©κ³Ό κ°™μŠ΅λ‹ˆλ‹€.
I did not modify any other theme files. They are identical to the contents of myapp26.

— themeexλŠ” ν…ŒμŠ€νŠΈμš© ν…Œλ§ˆλ‘œ PinaforeTheme.tsx와 거의 κ°™μŠ΅λ‹ˆλ‹€.
themeex is a test theme that is almost identical to PinaforeTheme.tsx.

— PinaforeTheme.tsxμ—λŠ” select메뉴뢀뢄을 themeNamesμ—μ„œ 읽어 μ˜΅λ‹ˆλ‹€.
In PinaforeTheme.tsx, the select menu section reads from themeNames.

'use client';
import { useTheme } from '@/lib/theme';
import { themeNames } from '../themeNames'; // βœ… myapp27
import { ThemeName } from '..';

... ...

          {/* βœ…myapp27 - ../themeNames.ts*/}
          <select value={theme || themeNames[0]} onChange={handleChange}>
            {themeNames.map(name => (
              <option key={name} value={name}>{name}</option>
            ))}
          </select>

πŸ“ ν…ŒμŠ€νŠΈ / Test

— μ‹ κ·œ ν…Œλ§ˆ 파일 μ—…λ‘œλ“œ / Upload New Theme File

etc % mv themeex /Users/gimdaegyeong/Desktop/app/NextJS/myapp27/app/usersui/[username]/_components/themes/
/Users/gimdaegyeong/Desktop/app/NextJS/myapp27/app/usersui/[username]/_components/themes/

etc % mv themeex /Users/gimdaegyeong/Desktop/app/NextJS/myapp27/app/usersui/'[username]'/_components/themes/

— μ„œλ²„ μš΄μ˜μ€‘ ν…Œλ§ˆ μ—…λ‘œλ“œμ‹œ ν…Œλ§ˆμ— μžλ™λ°˜μ˜λ©λ‹ˆλ‹€.

Server log
Timeline

πŸ“ 과정정리 / Process Summary

  1. μ‹€μ‹œκ°„ 파일 및 디렉토리 λ³€κ²½ 감기 확인 λͺ¨λ“ˆμ„€μΉ˜(chokidar)
    Install the module for real-time file and directory change monitoring (chokidar).
  2. ./lib/watchTheme.ts νŒŒμΌμƒμ„±(μ‹€μ‹œκ°„ 파일 λ³€κ²½ κ°μ‹œ μ„œλ²„)
    Create the ./lib/watchTheme.ts file (a server for monitoring real-time file changes).
  3. watchTheme.tsλ₯Ό λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ‹€ν–‰ν•˜κΈ° μœ„ν•΄μ„œ instrument.ts νŒŒμΌμƒμ„±
    Create the instrument.ts file to run watchTheme.ts in the background.
  4. watchThems.tsμ‹€ν–‰μ‹œ _components/themes디렉토리내에 index.ts와 themeNames.tsνŒŒμΌμ„ μƒμ„±ν•˜κ³  μˆ˜μ •ν•©λ‹ˆλ‹€.
    When watchTheme.ts runs, it generates and updates the index.ts and themeNames.ts files within the _components/themes directory.
  5. theme/page.tsxνŒŒμΌμ—μ„œ μƒμ„±λœ 파일(index.ts,themeNames.ts)을 λΆˆλŸ¬μ˜΅λ‹ˆλ‹€.
    Import the generated files (index.ts, themeNames.ts) into theme/page.tsx.
  6. 뢈러온 파일의 λ‚΄μš©κ³Ό μΌμΉ˜ν•˜λŠ” ν…Œλ§ˆλ₯Ό 뢈러였고 ν…Œλ§ˆ select메뉴에도 λ°˜μ˜ν•©λ‹ˆλ‹€.
    Load the theme corresponding to the content of the imported files and reflect it in the theme selection menu.

μš”ν•œλ³΅μŒ 8μž₯ 32절 / John 8:32

“그리고 λ„ˆν¬λŠ” 진리λ₯Ό μ•Œκ²Œ 될 것이며, 진리가 λ„ˆν¬λ₯Ό 자유둭게 ν•  것이닀.”

“Then you will know the truth ,and the truth will set you free”

Leave a Reply