gas-boilerplate
v1.0.2
Published
Boilerplate: Google Apps Script backend + React frontend + MCP
Maintainers
Readme
GAS Boilerplate
Boilerplate untuk membangun admin dashboard + API untuk AI (MCP) dengan biaya server Rp0: frontend React di-build jadi 1 file HTML dan di-serve langsung oleh Google Apps Script, data di Google Sheets.
web/ → React (Vite + Tailwind) — dibuild jadi 1 file HTML
src/ → Backend Google Apps Script (TypeScript, dibundle esbuild)
shared/→ Types + contract API (sumber kebenaran, dipakai frontend & backend)Quickstart
npm install
npm --prefix web install
# buat project GAS baru
npx clasp create --title "nama-app"
# build + deploy
npm run build
npx clasp push --force
npx clasp deploy
# ambil URL web app dari output deploy, lalu:
# 1. buka editor GAS → Properties → tambah API_KEY (dipakai MCP)
# 2. jalankan fungsi seedSampleData() sekali (bikin akun admin)
# 3. isi web/.env → VITE_DEPLOYMENT_ID=<deployment-id>Login default: [email protected] / admin123 (bisa diubah lewat halaman Staff).
Develop frontend (hot reload)
# isi web/.env dulu dengan VITE_DEPLOYMENT_ID, lalu:
npm run devVite proxy /exec → deployment GAS. Data tetap dipakai dari spreadsheet asli.
Scaffold project baru dari boilerplate
npm create gas-boilerplate@latest nama-app
# atau: npx gas-boilerplate nama-app
cd nama-app
npm install && npm --prefix web installBisa juga langsung dari repo ini: npm run create -- nama-app.
Scaffold menyalin boilerplate (tanpa node_modules/dist/.git/packages), mengganti nama
package, dan menyiapkan .clasp.json baru.
Menambah fitur baru (contoh pola: src/features/notes/)
- Entity →
shared/types.ts - Sheet →
src/features/<nama>/<Nama>Sheet.ts(extendsBaseSheet<T>) - Action →
src/features/<nama>/<nama>Feature.ts:registerAction({ name: 'notes.list', description: 'Lihat semua catatan', inputSchema: { type: 'object', properties: {} }, authLevel: 'user', handler: (args, ctx) => notes.getAll(), }) - Import di entry → tambah
import './features/<nama>/...'disrc/index.ts - Halaman →
web/src/pages/<Nama>.tsx+ route diweb/src/App.tsx+ menu diAppLayout.tsx
Action yang terdaftar otomatis menjadi:
- REST handler (
doPost→action+payload) - MCP tool (
tools/list+tools/call) — dengandescription+inputSchema - Frontend dipanggil lewat
api.*(withCacheuntuk baca,mutateuntuk tulis)
MCP (hubungkan ke AI)
MCP remote langsung menunjuk ke URL web app (JSON-RPC via doPost). Contoh (opencode):
{
"mcp": {
"nama-app": {
"type": "remote",
"url": "https://script.google.com/macros/s/<DEPLOY_ID>/exec?apiKey=<API_KEY>",
"enabled": true
}
}
}Arsitektur
shared/contract.ts → ActionDef (name, description, inputSchema, handler, authLevel)
src/core/registry.ts→ registerAction() — daftar action tunggal
src/core/http.ts → dispatcher REST (dari registry)
src/core/mcp.ts → JSON-RPC tools/list + tools/call (dari registry)
src/core/ → SheetManager, BaseSheet, session, staff, settings, config
src/features/notes/ → contoh feature (demo) — jadikan blueprint fitur kamu
web/src/lib/api.ts → satu-satunya layer frontend yang tahu backend (kontrak HTTP)Backend pluggable
Frontend tidak tahu apa-apa soal GAS — ia cuma berbicara lewat kontrak
(shared/contract.ts + web/src/lib/api.ts). Backend non-GAS (Express, Supabase, dst)
cukup implementasi kontrak yang sama; GAS hanyalah salah satu implementasi.
Perintah
| Perintah | Fungsi |
|---|---|
| npm run dev | Vite dev server (proxy /exec → GAS) |
| npm run build | tsc check + build web + bundle backend → dist/ |
| npm run typecheck | Cek tipe backend |
| npm run test | Jalankan unit test (vitest) |
| npm run lint | Lint (oxlint) |
| npm run check | typecheck + lint + test |
| npm run push | clasp push |
| npm run deploy -- "deskripsi" | build + push + clasp deploy (butuh VITE_DEPLOYMENT_ID di .env) |
| npm run create -- <app> | Scaffold project baru |
| npm run pack | Cek isi paket npm (npm pack --dry-run) |
Publish ke npm
npm publish # publish gas-boilerplate
cd packages/create-gas-boilerplate
npm publish # publish create-gas-boilerplatePastikan versi kedua paket sinkron dan sudah di-npm login.
Skrip GAS (jalankan dari editor)
| Fungsi | Kegunaan |
|---|---|
| seedSampleData() | Bikin akun admin + contoh catatan + appName |
| resetAllData() | Kosongkan semua sheet |
| resetSpreadsheet() | Bikin spreadsheet DB baru |
