Skip to content

[DONE] hardware+web: mbchars' horizontal desktop case (upstream #488) is the fourth case in the /build 3D preview - #5

Merged
engmung merged 6 commits into
devfrom
claude/horizontal-desktop-preview-qwlxhp
Oct 10, 2026
Merged

engmung merged 6 commits into
devfrom
claude/horizontal-desktop-preview-qwlxhp

Conversation

@patternflow-bot

@patternflow-bot patternflow-bot commented Oct 10, 2026 •

Copy link
Copy Markdown

dev / https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7

mbchars가 원래 레포 PR 488로 보낸 가로형 데스크톱 케이스를 작성자 커밋 그대로 가져오고, /build 3D 미리보기에서 공식 · Besoiobiy · SimonePDA 다음 넷째 케이스로 넣었습니다. 머지하면 리믹스 폴더와 카드 · 3D 모델이 들어오고, 화살표나 탭으로 네 케이스를 넘겨 볼 수 있습니다.

체크리스트

  • Horizontal desktop engmung/Patternflow#488 적용. git fetch https://github.com/engmung/Patternflow.git pull/488/head 의 커밋 a22659d 하나를 cherry-pick 했다. 작성자 Mykyta Bilous(mbchars)는 그대로다(0d23998). 리믹스 폴더(STL 10 · 3MF · README · assembly · bom · 사진), 빌드 갤러리 extraplojo → mbchars 이름 변경이 모두 들어 있다. 내용은 한 글자도 고치지 않았다(고칠 만큼 깨진 곳이 없었다).
  • 모델. tools/case-models/mbchars.py 가 리믹스의 STL 로 케이스를 조립한다. web/public/cases/mbchars-horizontal-desktop-printed/model.glb 는 380 KB 다. 다시 만들어도 바이트가 같고, 다른 세 모델도 바이트가 같다.
  • 미리보기 · 카드. 넷째 탭과 카드, 화살표 순환을 넣었다. 질감 규칙도 같다: 무광 PLA, 같은 pla_white, 둥근 공식 노브, 같은 조명 · 톤 커브.
  • 완료 기준. npm run build 와 check:ci 가 통과한다. 데스크톱에서 화살표로 네 케이스가 넘어가고, 폰 폭(390)에서도 새 케이스가 잘 보인다. 스크린샷은 아래에 있다(라이트).

What (한 일)

리믹스 — hardware/case/remixes/mbchars-horizontal-desktop-printed/: engmung#488 그대로(0d23998, author: Mykyta Bilous).

모델 — tools/case-models/

  • mbchars.py(새 파일). 이 리믹스에는 조립된 파일이 없고, 출력 자세 그대로의 부품 STL 만 있다. 그래서 형상에서 직접 맞춘다. 단계마다 확인하고, 하나라도 어긋나면 빌드가 멈춘다.
    1. 앞판 셋. 조인트 바의 인서트 간격(36 mm)만큼 양쪽 러그 구멍이 떨어지도록 놓는다. 제어부 · 안쪽 프레임 · 바깥 프레임이 0 / 74 / 242.14 mm 에 놓이고, 맞닿는 면이 실제로 닿는지 확인한다.
    2. 조인트 바 4개. 러그 밑에 인서트가 뒤를 향하게 놓는다.
    3. 뒷덮개 2개. 두 가지 뒤집기와 모든 위치를 시도한다. 접시 구멍 8개가 모두 인서트 위에 오는 경우는 하나뿐이고, 그 결과 16개 인서트가 각각 구멍 하나에 맞는다.
    4. USB 리테이너. 덮개용이 아닌 마지막 인서트 보스 위에 놓는다.
    5. 스탠드 2개. 단면에서 케이스 깊이만큼 넓은 홈을 찾아 끼운다. 홈이 기울어 있어 케이스가 뒤로 10° 기댄다.
    • 결과 검증: 410.28 × 176.16 × 42 mm(README 「약 411 × 176 × 42」), 엔코더 구멍 31 × 30.5 mm(보드 격자와 같음), 패널 구멍 320.8 × 160.8 mm, 부품끼리 겹치지 않음(manifold3d 불리언).
    • knob.stl 은 공식 노브와 같은 것임을 확인했다. 그래서 공식 둥근 노브를 흰색으로 쓴다.
  • assemble.mjs: ledTurn(패널을 자기 가운데에서 돌림)과 knobLook(공식 노브 재질)을 추가했다. 둘 다 없으면 전과 같다.
  • lib/looks.mjs: pla_orange 를 추가했다. 색은 작성자 3MF 의 필라멘트 색 #F46B16 이고, pla_white 처럼 무광 0.85 다.
  • build.sh · README.md: 넷째 케이스와 그 절을 추가했다.

웹 — web/

  • build-cases-data.ts: 넷째 카드다. README 의 사실과 사진 3장(1200 px 로 줄이고 메타데이터를 지움)을 썼다. 링크는 README · 3MF · assembly.md · bom.md · stl/ 이다.
  • 3d/cases/mbchars-horizontal-desktop-printed.ts: 분해 방향을 정했다. 바깥 프레임과 제어부는 이음매에서 벌어지고, 조인트 바는 뒤로, 패널과 노브는 앞으로, 보드 · DevKit · 덮개는 뒤로 빠진다. 스탠드는 아래로 떨어진다.
  • CasePicker: 탭 4칸이고 폰에서는 2×2 다. 머리글은 「four ways to make it」로 바꿨다.
  • buildPose.ts fitAcross · HeroScene.tsx: 화면 폭에 맞춘다(아래 「가정」 6).
  • content/build.md 첫 문단과 llms.txt: 리믹스 셋으로 고쳤다.
  • 테스트
    • buildPose.test.ts +2: 폰에서는 네 케이스가 모두 한 배율이다. 데스크톱에서도 세 케이스는 한 배율이고, 가로 케이스만 72% 폭에 맞는다.
    • heroCase.test.ts: width 를 확인한다.
    • BuildPanel.test.tsx: 탭 4개, 그리고 End · 순환 키 동작과 mbchars 카드를 확인한다.
    • build-cases-data.test.ts: 4개 id, 그리고 README 근거 표(「가정」 8)를 확인한다.
    • caseModels.test.ts 는 새 모델에도 자동으로 적용된다. 노드 계약, 재질, 예산 600 KB 를 본다.
  • CHANGELOG.md(Unreleased · Hardware, Web).

Why

과제대로다. 커뮤니티 리믹스를 포크 dev 에 들이고, 빌드 섹션 미리보기에서 다른 세 케이스와 같은 방식으로 볼 수 있게 했다.

Tested (증거)

화살표로 네 케이스 (데스크톱 1440×900, next start)

/build → Next 4번: ?case=besoiobiy-printed → ?case=simonepda-lasercut → ?case=mbchars-horizontal-desktop-printed → /build(다시 공식). 탭도 같이 넘어간다.

arrows

작성자 사진 vs 미리보기

photo vs preview

폰 폭 390 (라이트): 처음(폰은 단계 01 이 자동 선택) · 단계 04 점등 · 2×2 탭과 카드

phone

데스크톱: 카드와 함께 · 단계 01(부품) · 단계 03(완전 분해)

desktop card

steps

모델 네 방향 (tools/case-models/preview.mjs)

model

명령과 출력 (로컬, 이 브랜치)

tools/case-models$ ./build.sh                       → 네 모델; git status 에 기존 세 GLB 변화 없음(바이트 동일)
  front sections along x: control_section 0.00, inner_frame 74.00, outer_frame 242.14 (lug holes 36.00 apart across each joint)
  rear_control_cover x 0.00 … 205.04 / rear_display_cover x 205.24 … 410.28, all eight holes on inserts
  assembled 410.28 × 176.16 × 42.00 (README: about 411 × 176 × 42), no parts overlapping
  encoder holes 31.00 × 30.50 apart; opening 320.80 × 160.80; tabs 17.80 behind the front; leaning back 10.00°
  web/public/cases/mbchars-horizontal-desktop-printed/model.glb: 379676 bytes
tools/case-models$ ./build.sh mbchars-horizontal-desktop-printed  → md5 cb61598f… 전후 같음
web$ npm run lint        → ✖ 12 problems (0 errors, 12 warnings)   (모두 원래 있던 경고, 바뀐 파일에는 없음)
web$ npm run typecheck   → exit 0
web$ npm run build       → ✓ Compiled successfully · ✓ Generating static pages (134/134) · exit 0
web$ npm run check:ci    → exit 0 · Test Files 34 passed (34) · Tests 470 passed (470)
$ python3 .github/scripts/check_links.py           → all 579 relative links resolve
$ (community-surfaces.yml 의 README 헤더 검사를 그대로 실행) → exit 0
모델 크기 로드
official 317,180 B 그대로
besoiobiy-printed 344,752 B 그대로
simonepda-lasercut 331,760 B 그대로
mbchars-horizontal-desktop-printed 379,676 B 탭 hover · 선택 시

  • Touches web/ → it builds (npm run build)

실행법

cd web && npm ci && npm run dev     # http://localhost:3000/build?case=mbchars-horizontal-desktop-printed — 양옆 화살표로 넘긴다
cd tools/case-models && npm ci && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
./build.sh mbchars-horizontal-desktop-printed      # 새 모델 다시 만들기 (커밋된 것과 바이트 동일)
NODE_PATH=$(npm root -g) node preview.mjs ../../web/public/cases/mbchars-horizontal-desktop-printed/model.glb /tmp/mb.png

스크린샷은 헤드리스 Chromium(SwiftShader)으로 next start 에서 찍었다. 샌드박스가 gstatic CDN 을 막아서 Draco 디코더만 three 의 로컬 사본으로 돌려 썼다(코드 변경 없음).

가정

  1. 가져오기. 브랜치는 세션이 준 claude/horizontal-desktop-preview-qwlxhp(= dev 021e96f) 위에 있다. Horizontal desktop engmung/Patternflow#488 커밋을 cherry-pick 해서 author 를 살렸고, committer 만 다르다. 원래 레포와 Horizontal desktop engmung/Patternflow#488 에는 아무것도 하지 않았다. .claude/settings.json 은 dev 에 있던 그대로이고 건드리지 않았다.
  2. id = 폴더 이름. 과제의 「horizontal-desktop-printed」는 Horizontal desktop engmung/Patternflow#488 이 만든 폴더 mbchars-horizontal-desktop-printed 로 읽었다. 카드 데이터 규칙(id = 폴더 이름, /build?case= 가 경로처럼 읽힘)을 따른 것이다. 탭 이름은 다른 리믹스처럼 핸들 「mbchars」, 방법은 「Printed remix」다.
  3. 조립은 형상에서. 조립 파일이 없어서 위의 5단계로 맞췄다. 판단이 들어간 곳은 셋이다.
    • 스탠드 위치. README 에는 「각 아래 끝에」라고만 있다. 작성자 정면 사진에서 재니 각 끝에서 약 30 mm 안쪽이 스탠드 가운데였다.
    • 스탠드 끼움. 케이스 뒷면을 높은 쪽 벽에 붙였다. 뒤로 기대니 그쪽에 닿는다. 홈 여유는 0.6 mm 다.
    • USB 리테이너. 슬롯이 0.8 mm 미끄러지는데 가운데에 두었다.
    • 선택 부품인 정렬 핀 4개는 이음매 안에 숨어 보이지 않아서 넣지 않았다.
  4. 스탠드는 붙여 둠. 장치는 다른 케이스처럼 똑바로 서 있고, 스탠드는 케이스를 잡는 실제 각도(10°)로 붙어 있다. 그래서 스탠드 바닥이 조금 기울어 보인다. 사진에 스탠드가 늘 붙어 있어서 SimonePDA 발처럼 loose 로 빼지 않았다.
  5. 색 · 질감.
    • 출력표대로 프레임 · 덮개 · 조인트 바 · 노브는 흰색, 제어부 · 리테이너 · 스탠드는 주황이다.
    • 흰색은 기존 pla_white 이고, 주황은 3MF 의 #F46B16 이다. 둘 다 무광 0.85 다.
    • 노브는 STL 이 공식 노브와 같아서 공식 둥근 노브(lib/knob.mjs)를 흰색으로 썼다.
  6. 한 배율 규칙의 예외는 「안 들어갈 때만」.
    • 41 cm 폭 케이스를 같은 배율로 그리면 데스크톱의 세로로 긴 캔버스에서 양옆이 잘리고 화살표에 덮인다.
    • 그래서 fitAcross 를 넣었다. 쉬고 있을 때 장치가 화면 폭의 72% 를 넘을 때만 그만큼 줄인다. 1440×900 에서는 0.75 배다.
    • 폰에서는 네 케이스 모두, 데스크톱에서는 세 케이스가 그대로다(테스트로 고정).
    • 기준은 확대 전 화면 폭이다. 그래서 확대해도 장치가 줄지 않는다.
    • 이전 PR 이 없앤 fitScale(큰 케이스를 늘 줄이던 것)과는 다르다. 다만 캔버스가 가로:세로 0.67 보다 좁은 창에서는 가장 넓은 Besoiobiy 도 조금 줄어든다(지금은 그런 창에서 화살표에 닿는다).
  7. 패널 방향.
    • 이 케이스는 패널을 가로로 둔다. 그래서 ledTurn: -90(앞에서 보아 시계 방향 90°)으로 돌렸다. 그러면 패턴 128×64 프레임의 위가 위로 온다.
    • 근거는 작성자 뒷면 사진이다. 패널 화살표가 위를 향한다. 펌웨어는 건드리지 않았다.
  8. 테스트 하나를 표로 바꿈(약화 아님).
    • build-cases-data.test.ts 는 「모든 리믹스 README 에 (4 and 6) 이 있다」고 가정했다. mbchars README 는 절 번호 대신 「BOM changes(bom.md) … illustrated assembly instructions(assembly.md)」라고 쓴다.
    • Horizontal desktop engmung/Patternflow#488 내용을 고치지 않으려고 리믹스별 근거 표(GUIDE_BACKING)로 바꿨다. 기존 두 리믹스는 같은 단언을 그대로 받는다.
    • 새 리믹스도 표에 항목이 없으면 실패하고, 카드 문구가 README 문구에 묶인다.
  9. 카드에 「USB」 없음.
    • 하드 규칙 6과 테스트 「never offers USB-C as power」 때문이다.
    • 트리거 모듈은 「PDSink 303PDSink01 trigger module … feeds J4, the screw terminal, at 5 V」로, USB retainer 는 「module retainer」로 썼다.
    • 리믹스 README 자체의 표현은 Horizontal desktop engmung/Patternflow#488 원문이라 그대로 두었다. README 도 「J4 is the controller's only power input」이라고 쓴다.
  10. 남긴 것(범위 밖).

원본: engmung#488 — 케이스 설계 · 사진 · 조립 설명은 Mykyta Bilous (@mbchars), CC BY-SA 4.0. 이 PR 은 그 커밋(a22659d)을 작성자 그대로 담고 있다.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7

mbchars and others added 6 commits October 10, 2026 08:54
mbchars.py puts the remix's printed parts together from its STLs (no
assembled file exists): the three front sections where the joint bars'
36 mm insert pitch puts their lug holes, the covers on the sixteen inserts,
the USB retainer on its boss and the stands on the bottom edge, each step
checked against the README (410.28 x 176.16 x 42 mm), the board's encoder
grid, the 320 x 160 mm panel and boolean overlaps. assemble.mjs learns
ledTurn (the panel lies the long way here) and knobLook (the official knob,
printed white), and lib/looks.mjs pla_orange, the 3MF's own #F46B16. The
other three models rebuild byte-identical; the new one is 380 KB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7
…horizontal desktop one

The card is the remix README's own facts and photos (resized to 1200 px),
the preview shows the device in the case, and the switch is four tabs, two
by two on a phone. A case too wide for the view at the one scale (this one,
41 cm across on a desktop's tall canvas) is drawn smaller by as little as
keeps it clear of the arrows; every case still fits at the one scale on a
phone, and the three upright ones on a desktop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7
…review case

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7
…iew (removed in the next commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBYm64PnfneJq2ZDJ8Gs7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants