シェル壁紙
このチュートリアルでは、シェルコマンドを実行し、ターミナルエミュレータで出力を表示する壁紙を作ります。
前提条件
先にはじめようチュートリアルを完了してください。
シェルコマンドの宣言
fluxlay.yaml に shell セクションを追加します。
schemaVersion: 1
name: System Monitor
slug: system-monitor
version: 0.1.0
kind: web
description: ライブなシステム情報を表示する壁紙。
shell:
macchina:
run: macchina
reason: スタイル付きでシステム情報を表示します。
required:
- macchina
fetch-ip:
run: curl -s https://httpbin.org/ip | jq -r '.origin'
reason: パブリック IP アドレスを取得します。
required:
- curl
- jq
network:
- origin: https://httpbin.org
reason: パブリック IP アドレスの取得に使用します。
各コマンドには reason(なぜ必要か)と required(依存するプログラム)の宣言が必要です。ユーザーはコマンド実行前に承認を求められます。
ターミナル出力の表示
スタイリング用に Tailwind CSS をインストールします。
pnpm add -D tailwindcss @tailwindcss/vite
vite.config.ts に Tailwind プラグインを登録します。
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import { fluxlay } from "@fluxlay/vite";
export default defineConfig({
plugins: [react(), tailwindcss(), fluxlay()]
});
src/main.tsx を更新します。
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { useTerminal, useShell, TerminalThemes } from "@fluxlay/react";
import "./index.css";
function SystemMonitor() {
const { terminalRef, instance } = useTerminal({
fontSize: 13,
theme: TerminalThemes.tokyoNight
});
const { error } = useShell("macchina", {
terminal: instance,
refreshInterval: 60000
});
return (
<main className="h-screen w-screen bg-zinc-900 p-8">
<div className="h-full w-full rounded-xl overflow-hidden border border-zinc-700">
{error && <p className="p-4 text-red-400 text-sm">{error}</p>}
<div ref={terminalRef} className="h-full w-full" />
</div>
</main>
);
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<SystemMonitor />
</StrictMode>
);
src/index.css を作成します。
@import "tailwindcss";
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
runShell でカスタム表示
表示を自分で制御したい場合は runShell を使います。
import { useEffect, useState } from "react";
import { runShell } from "@fluxlay/react";
function IpAddress() {
const [ip, setIp] = useState<string>("...");
useEffect(() => {
const fetchIp = async () => {
const result = await runShell("fetch-ip");
if (result.success) setIp(result.stdout.trim());
};
fetchIp();
const id = setInterval(fetchIp, 30000);
return () => clearInterval(id);
}, []);
return <p className="text-zinc-400 text-sm">Public IP: {ip}</p>;
}
次のステップ
タスクごとの詳しいガイド:
完成したら:
API リファレンス: