# qpost 개발 지침

## 프로젝트

- qpost는 `stancl/tenancy` 기반의 멀티테넌트 플랫폼이다.
- `reference_laravel` 폴더는 구버전 프로젝트이며 코드 참고용으로만 사용한다.
- `reference_laravel`의 파일은 직접 수정하지 않는다.

## 아키텍처

- Central과 Tenant를 명확히 분리한다.
- Platform(Central)은 회원, 게시판, 결제, 사이트 생성, 테넌트 관리, 플랫폼 전용 관리 기능을 담당한다.
- 서비스 데이터는 각 Tenant가 독립적으로 관리한다.
- 모든 기능은 멀티테넌트 환경을 전제로 설계한다.
- 싱글 테넌트를 가정하지 않는다.
- 게시판, 회원, 글, 댓글은 공용 코어를 두고 Central/Tenant에서 얇은 컨트롤러와 뷰로 분리한다.
- `app/Core` 아래에는 공통 코드만 두고, tenant/platform 전용 하위 폴더를 만들지 않는다.
- 공통 코어는 기능별로 나누되, Tenant 전용 코드와 Platform 전용 코드를 혼용하지 않는다.
- 모델 네임스페이스는 `App\Models\Tenant`와 `App\Models\Platform`으로 구분한다.

## 테넌트

- 사이트 생성 시 하나의 Tenant가 생성된다.
- 각 Tenant는 독립적인 SQLite 데이터베이스를 가진다.
- 회원, 글, 이미지, 설정 등 모든 데이터는 테넌트별로 완전히 분리한다.
- 테넌트 간 데이터 공유는 하지 않는다.
- Tenant 모델은 Central 데이터를 직접 참조하지 않는다.
- Tenant DB와 Central DB를 혼용하지 않는다.
- Tenant 전용 화면은 `resources/views/tenant/*`, Platform 전용 화면은 `resources/views/platform/*`로 나눈다.

## 접속 방식

- MVP는 `domain.com/sites/{tenantId}` 방식으로 제공한다.
- 추후 `{tenant}.qpost.com` 및 독립 도메인을 지원한다.
- 하나의 Tenant는 여러 Domain을 가질 수 있다.
- Domain 정보는 domains 테이블에서 관리한다.
- 코드에서 Tenant ID를 하드코딩하지 않는다.

## 코드 구조

- 모든 Tenant는 하나의 Laravel 코드베이스를 공유한다.
- 중앙 코드 변경은 모든 Tenant에 즉시 반영되어야 한다.
- Tenant별 소스코드 복제 및 별도 프로젝트 생성은 금지한다.
- Tenant별 차이는 데이터와 설정으로만 관리한다.
- 기능 차이는 Feature Flag 또는 Plan으로 제어한다.
- 기존 패턴과 일관성을 유지하며 불필요한 새로운 구조를 만들지 않는다.

## 파일

- 업로드 파일은 Tenant별로 분리한다.
- 기본 경로는 `storage/app/tenants/{tenantId}`이다.
- 이미지, 첨부파일, 캐시 파일이 섞이지 않도록 한다.

## 인프라

- Queue, Cache, Session, Event, File은 Tenant 컨텍스트를 고려한다.
- Migration은 Central과 Tenant를 분리한다.
- 새로운 기능은 Tenant 수가 증가해도 구조 변경 없이 확장 가능해야 한다.
- 향후 MySQL 등 다른 DB로 전환 가능하도록 구현한다.

## Blade 규칙

- 레이아웃은 `<x-layouts.*>` 컴포넌트를 사용한다.
- tenant 전용 레이아웃은 `resources/views/tenant/layouts/*` 아래에 둔다.
- 공용 레이아웃과 Platform 레이아웃은 `resources/views/components/layouts/*` 아래에 둔다.
- tenant 관리자 화면은 `<x-layouts.tenant-admin>`만 사용하고 `tenant.admin-layout`은 사용하지 않는다.
- Platform 관리자 화면은 `<x-layouts.platform-admin>`을 사용한다.
- 페이지 데이터는 Props 또는 Named Slot로 전달한다.
- 재사용 UI는 `<x-ui.*>` 컴포넌트로 작성한다.
- tenant 전용 익명 컴포넌트는 `resources/views/tenant/components/*` 아래에 둔다.
- tenant 전용 컴포넌트는 `<x-tenant::...>` 네임스페이스를 사용한다.
- `resources/views/components` 아래에는 공용 컴포넌트만 둔다.
- 큰 화면 영역은 별도 컴포넌트로 분리한다.
- 단순 분리만 필요한 경우 `@include`를 사용한다.
- 스타일은 Tailwind 클래스로 작성한다.
- 인라인 `style=""` 작성은 금지한다.
- PHP 파일 내부에 CSS 작성은 금지한다.
- 중복되는 스타일은 UI 컴포넌트 또는 공통 CSS로 분리한다.
- 뷰에는 비즈니스 로직을 작성하지 않는다.
- Platform 게시글/댓글은 `platform.posts.*`, `platform.comments.*`, `platform.files.*` 라우트 규칙을 사용한다.

## 디자인 규칙

- 스타일은 Tailwind 유틸리티와 프로젝트에서 제공하는 디자인 클래스만 사용한다.
- CSS 변수(`--color-*`, `--text-*`)를 직접 사용하지 않는다.
- 디자인 토큰 값을 직접 참조하거나 새로운 토큰을 추가하지 않는다.
- Tailwind 기본 색상(`text-gray-*`, `bg-blue-*`, `text-red-*`)은 사용하지 않는다.
- 인라인 `style=""` 작성은 금지한다.
- PHP 파일 내부에 CSS 작성은 금지한다.
- 중복되는 스타일은 UI 컴포넌트 또는 공통 CSS로 분리한다.
- 그림자와 카드 남용을 피하고 spacing, border, typography 중심으로 디자인한다.
- Linear, Vercel, Notion 스타일처럼 여백과 레이아웃 중심으로 구성한다.

### 사용 가능한 텍스트 색상

`c-main`
`c-muted`
`c-subtle`
`c-primary`
`c-secondary`
`c-accent`
`c-success`
`c-warning`
`c-danger`
`c-info`

### 사용 가능한 글자 크기

`text-xs`
`text-sm`
`text-base`
`text-md`
`text-lg`
`text-xl`
`text-2xl`
`text-3xl`

### 사용 가능한 배경색

`bg-base`
`bg-surface`
`bg-surface1`
`bg-surface2`
`bg-card`

### 사용 가능한 강조 배경

`bg-primary-soft`
`bg-secondary-soft`
`bg-accent-soft`
`bg-success-soft`
`bg-warning-soft`
`bg-danger-soft`
`bg-info-soft`

### 색상 규칙

- 색상은 반드시 위 클래스만 사용한다.
- 색상은 `c-*`, `bg-*`, `text-*` 같은 테마 유틸을 우선 사용한다.
- CSS 변수값을 직접 참조하지 않는다.
- 새로운 색상 클래스를 임의로 만들지 않는다.
- 필요한 색상이 없다면 기존 클래스 조합으로 해결하고, 정말 필요한 경우에만 공통 CSS에 추가한다.

## 개발 원칙

- 단순함을 우선한다.
- 기존 구조와 일관성을 유지한다.
- 과도한 추상화와 불필요한 패턴 추가를 피한다.
- 특별한 이유가 없다면 새로운 라이브러리를 추가하지 않는다.
- 기능 추가 시 확장성을 고려하되 조기 최적화는 하지 않는다.

## AI 글쓰기 출력 계약

- AI 글쓰기의 작성 지침은 사이트설정 기본 프롬프트 또는 사용자 입력 프롬프트로 결정한다.
- 모델 출력 형식과 HTML 허용 규칙은 애플리케이션 코드의 고정 계약으로 관리한다.
- 허용 키는 `title`, `content`, `meta_description`, `tags`, `meta_keywords`이다.
- `content`는 Tiptap 편집기에 바로 넣을 수 있는 HTML이어야 한다.
- `tags`와 `meta_keywords`는 배열로 반환한다.

# Tenant URL rule:

- tenant 화면의 URL, form action, redirect에서는 `route('tenant...')`를 직접 사용하지 않는다.
- 일반 tenant URL은 `tenant_url(...)`
- tenant admin URL은 `tenant_admin_url(...)`
- 로그인 URL은 `tenant_login_url(...)`
- 현재 tenant의 접근 방식(path / subdomain / custom domain)을 항상 유지한다.
- 예외적으로 `route()`를 사용해야 한다면 현재 host 유지 여부를 반드시 확인한다.
