diff --git a/docs/design-system.md b/docs/design-system.md index 40b7eff7..d6d2deb0 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -53,4 +53,5 @@ | posimai-journal | `#80CAEE` Sky-Blue | `#0284C7` | CMS 系・静かで知的な印象 | | posimai-site | `#80CAEE` Sky-Blue | `#0284C7` | journal と同系統の公開サイト | | posimai-atlas | `#22D3EE` Cyan | `#0891B2` | インフラ/ネットワーク管理 — ターミナル・サイバー感。背景も `#0C1221` navy に変更 | +| posimai-dev | `#A78BFA` Violet | `#7C3AED` | 開発ポータル — コード・AI・ターミナルの融合。Atlas と差別化 | | ponshu-room | `#D4A574` 琥珀(Amber) | `#D4A574` | **Posimai デザインシステム適用外**。独自テーマ(和紙×墨×琥珀)を使用 | diff --git a/posimai-dev/index.html b/posimai-dev/index.html new file mode 100644 index 00000000..b1aec9a5 --- /dev/null +++ b/posimai-dev/index.html @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + posimai-dev + + + + + + + + + + + + + + + + +
+
+ + posimai-dev + 接続中... +
+
+ + +
+
+ +
+ + + + + diff --git a/posimai-dev/manifest.json b/posimai-dev/manifest.json new file mode 100644 index 00000000..74ab4983 --- /dev/null +++ b/posimai-dev/manifest.json @@ -0,0 +1,14 @@ +{ + "name": "posimai-dev", + "short_name": "dev", + "description": "posimai development portal", + "start_url": "/", + "display": "standalone", + "background_color": "#0D0D0D", + "theme_color": "#0D0D0D", + "orientation": "any", + "icons": [ + { "src": "/logo.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/logo.png", "sizes": "512x512", "type": "image/png" } + ] +} diff --git a/posimai-dev/package.json b/posimai-dev/package.json new file mode 100644 index 00000000..20279f7e --- /dev/null +++ b/posimai-dev/package.json @@ -0,0 +1,14 @@ +{ + "name": "posimai-dev", + "version": "0.1.0", + "description": "posimai development portal — self-hosted terminal + AI dev environment", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "4.19.2", + "node-pty": "1.0.0", + "ws": "8.18.0" + } +} diff --git a/posimai-dev/server.js b/posimai-dev/server.js new file mode 100644 index 00000000..81a0bffa --- /dev/null +++ b/posimai-dev/server.js @@ -0,0 +1,46 @@ +'use strict'; +const express = require('express'); +const { WebSocketServer } = require('ws'); +const pty = require('node-pty'); +const http = require('http'); +const path = require('path'); + +const app = express(); +const PORT = process.env.PORT || 3333; + +app.use(express.static(path.join(__dirname))); + +const server = http.createServer(app); +const wss = new WebSocketServer({ server, path: '/terminal' }); + +wss.on('connection', (ws) => { + const shell = process.env.SHELL || '/bin/bash'; + const ptyProc = pty.spawn(shell, [], { + name: 'xterm-256color', + cols: 80, + rows: 24, + cwd: process.env.HOME || '/home/ubuntu-pc', + env: process.env + }); + + ptyProc.onData((data) => { + if (ws.readyState === 1) { + ws.send(JSON.stringify({ type: 'output', data })); + } + }); + + ws.on('message', (raw) => { + try { + const msg = JSON.parse(raw.toString()); + if (msg.type === 'input') ptyProc.write(msg.data); + if (msg.type === 'resize') ptyProc.resize(Number(msg.cols), Number(msg.rows)); + } catch {} + }); + + ws.on('close', () => { try { ptyProc.kill(); } catch {} }); + ptyProc.onExit(() => { try { ws.close(); } catch {} }); +}); + +server.listen(PORT, '0.0.0.0', () => { + console.log(`posimai-dev running on http://0.0.0.0:${PORT}`); +}); diff --git a/posimai-dev/sw.js b/posimai-dev/sw.js new file mode 100644 index 00000000..af5ddd10 --- /dev/null +++ b/posimai-dev/sw.js @@ -0,0 +1,24 @@ +const CACHE = 'posimai-dev-v1'; +const SHELL = ['/']; + +self.addEventListener('install', (e) => { + e.waitUntil(caches.open(CACHE).then((c) => c.addAll(SHELL))); + self.skipWaiting(); +}); + +self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then((keys) => + Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))) + ) + ); + self.clients.claim(); +}); + +// ターミナルのWebSocket通信はキャッシュしない +self.addEventListener('fetch', (e) => { + if (e.request.url.includes('/terminal')) return; + e.respondWith( + caches.match(e.request).then((r) => r || fetch(e.request)) + ); +});