Opentrons Labworks Inc
Opentrons Flex와 OT‑2용 프로토콜 작성 및 실행 소프트웨어
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기食べたものを写真で残し、食べすぎたかを○×で振り返る食事日記PWA(Next.js / TypeScript / IndexedDB)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗写真とかんたんな記録を日付ごとに残し、月のカレンダーで振り返るスマホ向けの日記アプリを、共通の土台(packages/journal/)の上に2つ作りました。
どちらも記録は端末内(IndexedDB)にだけ保存し、サーバーには送りません。ホーム画面に追加してアプリのように使えます(PWA)。
| アプリ | 内容 | デモ |
|---|---|---|
食事日記(apps/meal/) | 食べたものを写真で残し、その日に「食べすぎたか」を ○ / × で付ける。1日1件 | https://meal-diary-sable.vercel.app |
釣果ノート(apps/fishing/) | 釣行ごとに釣果・釣り場・天気・潮・風・仕掛けを記録する。1日に複数件 | https://fishing-log-chi.vercel.app |
スマホで開き、ホーム画面に追加して使うのがおすすめです。
| 分類 | 使用技術 |
|---|---|
| フレームワーク | Next.js 16(App Router)、React 19、TypeScript |
| スタイル | SCSS(CSS Modules)、デザイントークン(primitive / semantic の2層) |
| データ保存 | IndexedDB(Dexie.js 4、dexie-react-hooks) |
| テスト | Vitest、fake-indexeddb、Playwright(画面と画像処理の検証) |
| ホスティング | Vercel |
汎用的な部分(packages/journal/)とアプリに固有の部分(apps/meal/、apps/fishing/)を分け、1つのリポジトリで複数のアプリを管理する構成(npm workspaces)にしています。釣果ノートは、この土台の上に後から作りました。
Entry<TFields> 型で表し、アプリ固有の項目は型引数で渡します。食事日記では { overate: boolean | null }、釣果ノートでは釣り場・天気・潮・風・仕掛けと、魚種ごとの釣果の配列ですgetBadge 関数で、その日の記録の一覧から印(○× や合計匹数)を作って渡します。1日1件の食事日記も、1日に複数件の釣果ノートも同じ部品で表示できますJournalRepository インターフェースだけです。将来クラウド保存(Supabase)に移るときは、その実装を差し替えるだけで済みます保存ボタンは置かず、入力が止まって0.5秒たったら保存します(useDebouncedSave)。画面を離れるときと、アプリが裏に回ったとき(visibilitychange)は待たずに保存するので、入力の途中でアプリを閉じても消えません。釣果ノートの匹数・サイズ・風速は、入力中は文字列のまま持ち、保存するときに数値に直します。数値で持つと、「23.」のような入力の途中の値が「23」に戻ってしまうためです。
createdAt / updatedAt で持ちます。将来クラウドと同期するときに、ID が衝突せず、どちらが新しいかを比べられますundefined ではなく null で表します。値が入っていない状態と、項目そのものがない状態を区別するためです撮った写真は createImageBitmap で読み込み、canvas に描き直してから JPEG で保存します。描き直した画素だけが残るので、位置情報などの EXIF は一緒に保存されません。回転情報は描画の前に反映されるため、向きもずれません。この挙動は、位置情報と回転情報を埋め込んだ画像を使って実際のブラウザで確かめています。
日付は "YYYY-MM-DD" のローカル日付で扱います。toISOString() は UTC で計算するため、日本時間の朝9時より前に記録すると前日の日付になってしまいます。これを避けるためです。「今日」はサーバー(UTC・ビルド時刻)では決めず、端末側で useSyncExternalStore を使って求めます。
| 起きた問題 | 対応 |
|---|---|
| メモを入力してキーボードを閉じると、画面が押し上げられたまま戻らない | body に overflow: hidden を付けて内側だけスクロールさせる作りをやめ、ページ全体をスクロールさせる。タブバーと操作バーは sticky で画面下に固定する |
| 16px 未満の入力欄にフォーカスすると、画面が拡大される | 入力欄の文字は 16px 以上にする |
capture 属性を付けると、アルバムから選べなくなる | 「撮る」(capture あり)と「選ぶ」(capture なし)でボタンを分ける |
| Safari とホーム画面のアプリで、データが別々に保存される | Safari で開いたときにホーム画面への追加を案内し、記録を始める場所をアプリに揃える |
| 7日間使わないとデータが消えることがある | ホーム画面に追加すると、この削除の対象外になる。あわせて navigator.storage.persist() を呼ぶ |
packages/journal/ # 汎用層:型、Repository、Dexie の実装、フック、部品(カレンダー・写真・メモ・タブバーなど)、日付・画像処理
apps/meal/src/
├─ app/ # ルーティング(今日 / 日付指定 / カレンダー)、manifest
├─ meal/ # 食事日記に固有の部分:項目の型、○× の切り替え、画面
└─ styles/tokens/ # デザイントークン(primitive / semantic)。オレンジ系
apps/fishing/src/
├─ app/ # ルーティング(今日 / 日付指定 / 釣行 / カレンダー)、manifest
├─ fishing/ # 釣果ノートに固有の部分:項目の型、入力値の変換、並べ替え・集計、画面
└─ styles/tokens/ # デザイントークン。青系
共通の部品は semantic トークン(CSS 変数)だけを参照しています。2つのアプリは同じ変数名で値だけを変えているので、同じ部品のまま見た目が変わります。
npm install # リポジトリ直下で実行(全ワークスペースが入る)
npm run dev:meal # http://localhost:3000
npm run dev:fishing # http://localhost:3001
npm run dev:lan --workspace=apps/meal # 同じ Wi-Fi のスマホから http://<MacのIP>:3000 で開く(釣果ノートは apps/fishing、3001)
npm test # Vitest(日付計算・Repository・画像の寸法計算・釣果の入力変換と集計)
npm run typecheck # 各ワークスペースの型チェック
npm run build
LAN の http から開いた場合、HTTPS でしか使えない API(storage.persist() など)は動きません。ホーム画面への追加もうまく確認できません。これらの確認は、デプロイした後に本番の URL で行ってください。
スクリーンショットの料理写真には、Wikimedia Commons で CC0(パブリックドメイン)として公開されている画像を使い、実際にアプリへ読み込ませて撮影しました。