Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
건물 옥상에 태양광 모듈 배치를 설계하고 발전 시뮬레이션 입력을 받는 웹 애플리케이션입니다. Google Maps 위성 이미지에서 대상 영역을 크롭하고, 크롭 팝업의 캔버스 에디터에서 지붕 면과 개구부를 그리면 자동으로 최적 배치를 계산합니다. 일본어/영어 인터페이스를 지원합니다.README 전문 보기 ↗
건물 옥상에 태양광 모듈 배치를 설계하고 발전 시뮬레이션 입력을 받는 웹 애플리케이션입니다. Google Maps 위성 이미지에서 대상 영역을 크롭하고, 크롭 팝업의 캔버스 에디터에서 지붕 면과 개구부를 그리면 자동으로 최적 배치를 계산합니다. 일본어/영어 인터페이스를 지원합니다.
html2canvas) → 크롭 팝업 진입select 선택/이동, drawRoof 지붕면, drawOpening 개구부(제외 영역), flowSetting 처마(흐름방향), mergeSelected 지붕면 병합, editRoof 꼭짓점 편집, deleteSelected, deleteAll, undoflowSetting으로 지정한 처마 변(eave)에 평행하도록 그리드 정렬<html lang> 속성 자동 동기화| 기술 | 버전 | 용도 |
|---|---|---|
| Next.js | 16.2.0 | App Router, output: "standalone", React Compiler 활성화 |
| React | 19.2.4 | React Compiler |
| TypeScript | ^5 | strict mode |
| Tailwind CSS | v4 | @tailwindcss/postcss (CSS 커스텀 프로퍼티 기반) |
| @vis.gl/react-google-maps | ^1.7.1 | Google Maps 통합 |
| html2canvas | ^1.4.1 | 지도 영역 캡처 |
| lucide-react | ^0.577.0 | 아이콘 |
| polygon-clipping | ^0.15.7 | 지붕면 병합용 폴리곤 boolean 연산 (union / intersection) |
| OpenRouter API | — | 지붕 자동 감지 추론 (Chat Completions). 전용 SDK 없이 fetch 로 직접 호출 |
| zod | ^4.3.6 | AI 응답·요청 스키마 검증 (최종 SSOT) |
| babel-plugin-react-compiler | 1.0.0 | React Compiler |
| ESLint | ^9 | flat config (eslint-config-next) |
pnpm install
.env.local 파일에 Google Maps API 키를 설정합니다:
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_api_key_here
OPENROUTER_API_KEY=your_openrouter_api_key_here
OPENROUTER_MODEL=openai/gpt-5.6-sol
QSP/MUSBI BFF API(모듈 목록 조회 등)와 API 문서(/reference)를 로컬에서 호출하려면 dev 전용 키(QSP_API_HOST, MUSBI_API_HOST, ENABLE_API_DOCS)도 필요합니다. 이 키들은 .env.dev에 있지만 next dev는 .env.dev 파일명을 자동 로드하지 않습니다 — Next.js가 자동 로드하는 파일은 .env · .env.local · .env.development 등으로 한정되며, .env.dev/.env.prod는 배포 시 Jenkins가 .env로 병합하는 용도입니다. 따라서 로컬에서는 .env.dev를 .env.local로 복사해 사용합니다:
cp .env.dev .env.local # 기존 .env.local 이 있으면 append: cat .env.dev >> .env.local
.env.local은.gitignore대상이라 커밋되지 않습니다.- env 파일은 서버 시작 시점에만 로드되므로, 복사 후
pnpm dev를 재시작해야 적용됩니다.
개발 서버 실행:
pnpm dev
http://localhost:3000에서 확인합니다.
pnpm build # next build (standalone output)
pnpm start # 프로덕션 서버
pnpm lint # ESLint
npx tsc --noEmit # 타입 체크
.env 파일에 API 키를 설정한 후:
docker compose up --build # 빌드 및 실행
docker compose up --build -d # 백그라운드
docker compose down # 중지
단독 빌드:
docker build --build-arg NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your_api_key_here -t solar-pv-system .
docker run -p 3000:3000 \
-e OPENROUTER_API_KEY=your_openrouter_api_key_here \
-e OPENROUTER_MODEL=openai/gpt-5.6-sol \
solar-pv-system
좌측 사이드바(설계/시뮬레이션 탭)와 우측 Google Maps 메인 영역으로 구성된 SPA입니다. 크롭 후에는 메인 영역 위에 CropPopup(폴리곤 편집/패널 배치 캔버스)이 오버레이됩니다.
src/app/
├── components/
│ ├── AiDetectControls.tsx # AI 지붕 분석 트리거 (분석 시작/취소, prod 프로파일에서는 미렌더)
│ ├── CropPopup.tsx # 크롭 이미지 위 캔버스 폴리곤 에디터 + 패널 렌더링
│ ├── MapView.tsx # Google Maps + 크롭 영역 선택 오버레이 (html2canvas 캡처)
│ ├── RoofEditToolbar.tsx # 지붕 편집 툴바 (지도 위 플로팅)
│ └── lnb/ # 좌측 사이드바 (Lnb / LnbDesign / LnbSim / address-input-lnb)
├── utils/
│ ├── i18n.ts # 일/영 번역 사전 + `t(key, lang)` 함수
│ ├── mergePolygons.ts # 지붕면 병합 (인접 판정 + 폴리곤 union)
│ └── panelPlacement.ts # 좌표 변환 및 패널 배치 계산 엔진
├── types/index.ts # 도메인 타입
├── globals.css # CSS 커스텀 프로퍼티 테마
├── layout.tsx # 루트 레이아웃 (Server Component)
└── page.tsx # 메인 페이지 (Client Component, 전역 상태 소유)
page.tsx가 모든 상태(언어, 탭, 크롭 데이터, 폴리곤 영역, 픽셀 영역, 배치된 패널, 시뮬레이션 입력 등)를 소유하고 자식 컴포넌트에 props로 전달하는 Props-Down / Callbacks-Up 패턴을 사용합니다. RoofEditToolbar의 활성 도구에서 CropPopup의 drawingMode(install/exclude/null)를 파생합니다.
utils/panelPlacement.ts)세 가지 진입점을 제공합니다:
| 함수 | 좌표계 | 단위 | 호출 위치 |
|---|---|---|---|
placePanels | lat/lng | mm | 지도 직접 배치 (크롭 미사용 경로) |
placePanelsOnCanvas | 픽셀 | mm | 내부 구현 |
placePanelsOnCanvasCm | 픽셀 | cm | UI 진입점 (크롭 팝업) |
공통 처리 단계:
metersPerPixel 스케일) 변환MARGIN_CM만큼 설치 폴리곤은 내부로 축소, 제외(개구) 폴리곤은 바깥으로 확장(개구 주변 이격)eaveEdgeIndex) 또는 폴리곤의 가장 긴 변을 기준축으로 그리드 생성page.tsx는 패널 긴 변을 처마와 평행하게(landscape 고정) 호출하며, 경사(寸)를 cos 투영 보정해 전달합니다. 배치 엔진은 처마선 기준으로 x·y 시작 위상을 스캔해 가장 많이 채워지는 결과를 채택하고, 오목 폴리곤·장애물은 패널 변 교차 검사로 제외합니다.
page.tsx에 고정값으로 선언되어 있습니다 (UI 입력 아님):
| 상수 | 값 | 의미 |
|---|---|---|
GAP_X_CM | 0.3 | 모듈 좌우 간격 (3 mm, 처마 평행) |
GAP_Y_CM | 3 | 모듈 상하 간격 (30 mm, 처마 수직) |
MARGIN_CM | 30 | 외주 여백 (300 mm) |
globals.css의 CSS 커스텀 프로퍼티(--bg-primary, --accent-blue, --radius-md 등)를 인라인 스타일로 적용합니다. Tailwind 유틸리티 클래스는 사용하지 않습니다.
src/app/types/index.ts)| 타입 | 설명 |
|---|---|
LatLng | 위도/경도 좌표 |
PanelSize | 모듈 크기 (label, width/height mm) |
PanelOrientation | "portrait" | "landscape" |
DrawingMode | "install" | "exclude" | null (RoofEditToolbar에서 파생) |
PolygonArea | lat/lng 폴리곤 (id, type, paths, eaveEdgeIndex?) |
PlacedPanel | lat/lng로 표현된 배치 패널 (polygonId, 4 corners) |
CropBounds | 크롭 영역의 SW/NE lat/lng |
CropData | 크롭 결과 (이미지 dataURL, bounds, address, zoom, sizeMeters) |
PixelPoint | 캔버스 픽셀 좌표 |
PixelPolygon | 픽셀 폴리곤 (id, type, points, eaveEdgeIndex?) |
PixelPanel | 픽셀로 표현된 배치 패널 (polygonId, 4 corners) |
drawRoof로 지붕면 폴리곤을 그립니다 (3점 이상 → 시작점 클릭으로 닫기)drawOpening으로 환기구 등 개구부(제외 영역)를 그립니다flowSetting으로 각 지붕면의 처마(흐름방향) 변을 지정하면 모듈이 그 변과 평행하게 배치됩니다editRoof로 꼭짓점을 드래그하거나 더블클릭으로 삭제undo는 지붕면·개구부를 그리는 중 마지막으로 찍은 점을 되돌립니다 (되돌릴 점이 있을 때만 활성화)| 프리셋 | 폭 (mm) | 높이 (mm) |
|---|---|---|
| Standard 60-Cell | 991 | 1,650 |
| Standard 72-Cell | 991 | 1,960 |
| Large Format | 1,134 | 2,278 |
| Custom | 사용자 지정 | 사용자 지정 |
| 변수 | 필수 | 설명 |
|---|---|---|
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY | ✅ | Google Maps API 키 (Maps JS / Places / Geometry) |
OPENROUTER_API_KEY | ✅ | OpenRouter API 키 (지붕 자동 감지). 서버 라우트에서만 사용하므로 NEXT_PUBLIC_ 접두사 금지. 미설정 시 detect-roof 가 500 |
OPENROUTER_MODEL | ✅ | 추론 모델 슬러그 (현행 openai/gpt-5.6-sol). 기본값이 없어 미설정 시 detect-roof 가 500 |
GEMINI_API_KEY / GEMINI_MODEL | — | OpenRouter 전환 후 미사용. 안정화 관측 기간 롤백 대비로 남겨둔 잔존 키 |