npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@200stack/static-forms-astro

v0.2.4

Published

Astro Static Forms adapter for 200stack build-time materialization.

Readme

Static Forms Astro adapter

checkboxes(複数選択)は 0.2.3 以上(core は 0.2.2 以上)・build protocol v2 が必要です。 電話番号 tel・URL url・日付 date・数値 number は 0.2.4 以上(core も 0.2.4 以上)・build protocol v2 が必要です。

v2 と開発表示は slotId だけで描画できます。slotId は、200stack のフォームの画面の「サイトに貼るコード」に入っている名前(コードに書く名前)です。本番の v2 は core が作った HTML をそのままページに埋め込みます。

---
import StaticForm from '@200stack/static-forms-astro/StaticForm.astro'
---
<StaticForm slotId="slot.contact" />

同じフォーム(コードに書く名前が同じもの)を1ページに複数置く場合は、2つ目以降に index={1}、index={2} のように異なる値を渡してください。既定は 0 です。同じ instanceId の2つ目以降は診断を表示し、送信の controller を起動しません。生成される ID は固定の CSS セレクタとして扱わないでください。

v2 と開発表示の言語はフォームの定義の lang (ja・en) に従います。言語ごとに別のフォームを作り、それぞれのページに置いてください。通常、コンポーネントへの lang 指定は不要です。定義に lang がないフォームだけ、lang="en" などで既定の文言を選べます。どちらも省略なら日本語です。定義と異なる lang を指定すると、本番ビルド・開発表示ともエラーになります。同じ言語の明示指定は省略と同じ結果です。integration の options に lang の既定はなく、コンポーネントへ渡します。

送信・戻る・確認の送信・noscript・状態・項目エラーと開発の案内は、解決した言語の辞書を使います。保存された項目名や submitLabel・backLabel などの文言は自動翻訳しません。backLabel は確認の mode: 'configured' で省略可能です。本番・開発のフォームルートには HTML の lang と既存の data-200stack-static-form-lang を出します。ページ全体の <html lang> はサイト側で指定してください。データ取得に失敗して定義が分からない開発診断は、コンポーネントの lang、省略なら日本語を使います。v1 の出力は従来の英語固定で、定義・adapter の lang を適用しません。StaticFormLang 型を adapter から import できます。

0.1.0 は 0.2.0 のビルド入力を読めません。新しい定義・入力を使うサイトは adapter と core・SDK を対応する版へ更新してください。

言語を足す手順

  1. core の src/core/messages.ts にフォーム文言・状態・検証エラー・開発診断をすべて持つ辞書を足し、staticFormLanguageNames に表示名を足します。StaticFormLang と wire schema の許可値は辞書のキーから導かれます。実行時の登録はしません。
  2. 管理画面の自動返信の固定文(件名・本文・HTML の lang とフォント)と、作成時の既定定義・言語選択を足します。
  3. core の dist と controller bundle、Worker の同梱 controllers、adapter の controller contract、agent の生成物を作り直し、browser import 境界・bundle 予算・core と adapters のテストを確認します。言語追加には controller の再配備も必要です。
  4. DB(管理画面) → Worker(新しい core と controller) → build-runtime → 管理画面 → npm の順で配備し、サイトを再ビルドします。

開発表示の重複診断には CSS の :has() を使い、JS は実行しません。:has() と埋め込みの <style> が使えるブラウザ・CSP が必要です。

route・outputPath は v1 入力でのみ必須です。v2 では使いませんが、渡された値は検証します。

v2 の StaticForm.astro は、固定入力の publicApiOrigin にある /v1/controller/astro-controller.<sha256>.js を module script として参照します。controller はサイトの出力へコピーしません。hash は同梱 bundle の SHA-256 全64桁です。

CSP を使うサイトは script-src に Static Forms の配信元ドメインを追加してください。

初版では Astro の ClientRouter によるページの差し替えに対応しません。フォームを含むページへの移動は通常のページ読み込みを使ってください。

ボット対策は、送信の前にブラウザの中で行う計算の確認(ALTCHA と互換の proof-of-work)です。controller が自分で解くので、外部のスクリプトや iframe を読まず、CSP に追加の配信元は要りません。

リリース時に scripts/build-controller.mjs が bundle・controller contract・contracts/controller-manifest.v2.json を生成します。manifest は { name, hash, file } の配列で、file はこのパッケージのルートからの相対パスです。配信側は各版の bundle を対応する URL へ配置し、公開済みの版を保持してください。

見た目を指定する(v2)

---
import StaticForm from '@200stack/static-forms-astro/StaticForm.astro'
import type { StaticFormStyle } from '@200stack/static-forms-astro'
const style = {
  section: { title: 'text-xl font-bold' },
  field: { root: 'mb-5', label: 'font-medium', error: 'text-rose-600' },
  email: { control: 'rounded border aria-[invalid=true]:border-rose-600' },
  radio: { group: 'grid gap-2', option: 'flex gap-2', input: 'size-4' },
  byName: { email: { label: 'text-indigo-800' } },
} satisfies StaticFormStyle
---
<StaticForm slotId="slot.contact" style={style} />

値はクラス名の文字列だけです。項目は field → 種類 (text / email / textarea / select / radio / checkbox) → byName[name] の順に連結します。この順は CSS の優先順位を保証しません。未知の byName、またはその項目の種類に合わない部品は警告し、後者は使いません。

style と lang はサーバーで HTML に反映し、v2 の client props には含めません。HTML の SHA-256 である semanticDomDigest が remount の key であり、HTML が変わると入力・フォーカス・送信状態をリセットします。エラーの入力は aria-invalid="true"、項目外枠は data-200stack-static-form-invalid、送信中の root は aria-busy="true" です。checkbox は consentText があれば fieldset > legend + label > input、select は先頭に空の選択肢を出し、確認画面は configured・generated とも入力内容を表示します。固定 CSS は nonce を受け取らないため CSP hash を使います。

| キー | DOM (part) | | --- | --- | | root / form | ルートの section / 内側の form | | section.root / .title / .description | section / h2 / p | | field.root、*.label / .description / .error | 項目 div、label または legend、説明 p、エラー p | | text・email・textarea・select の .control | input / textarea / select | | radio・checkbox の .group / .option / .input | fieldset / 選択肢 label / input | | formErrors / status / submit | 全体エラー / 状態 / 主送信 button | | privacy.root / .link | 案内 p / a | | confirmation.* | div / h2 / p / dl / div / dt / dd / buttons | | completion.* | 完了の div / h2 / p |

| style のキー | part の正確な値 | 本番の DOM | 開発の表示 | | --- | --- | --- | --- | | root / form | root / form | section / form | 外側の div[role=form] (root form) | | section.* | section / section-title / section-description | section / h2 / p | 同じ | | field.root / *.label / .description / .error | field / label / description / error | 項目 div / label または legend / p / p | 同じ | | text 系 .control | control | input / textarea / select | 同じ | | choice .group / .option / .input | group / option / input | fieldset / label / input | 同じ | | formErrors / status / submit | form-errors / status / submit | div / div / button | 出ない / 出ない / 無効の button | | privacy.* | privacy / privacy-link | p / a | 同じ | | confirmation.* | confirmation、confirmation-title、confirmation-description、confirmation-list、confirmation-item、confirmation-label、confirmation-value、confirmation-back、confirmation-send | div / h2 / p / dl / div / dt / dd / buttons | 出ない | | completion.* | completion / completion-title / completion-body | div / h2 / p | 出ない |

条件で出ない説明・確認・完了は指定しても効果がありません。consentText が無い checkbox には group と label がありません。theme と公開目印は v2 と開発表示だけで、v1 の出力には効きません。制御文字、JSON 全体 32 KiB、合成済み class 属性 2,000 バイトを超えるとビルドエラーです。開発表示も同じ検査・クラスを使います。Tailwind は完全なクラス名をソースに書き、v3 の content または v4 の @source にそのファイルを含めます。動的なクラスは検出されず、エラー用には aria-[invalid=true]:border-rose-600 のように書きます。

CSS の目印と theme.css

v2 本番と開発表示では各部品に data-200stack-static-form-part が付きます。複数の役割は空白区切りなので [data-200stack-static-form-part~="form"] のように ~= を使います。公開する目印は、部品名の data-200stack-static-form-part、項目外枠の data-200stack-static-form-type・-name・-required・-invalid です。name には .・: が入り得るため値を引用符で囲みます。name を変更すると name を狙った CSS と byName は黙って外れます。controller 実行時の要素と開発表示の説明文は公開契約外です。HTML は項目ごとに 100〜200 バイト、選択肢ごとに約 70 バイト増えます。

---
import '@200stack/static-forms-astro/theme.css'
import '../styles/static-form.css'
---
@layer static-forms;
[data-200stack-static-form-part~="root"] { --200stack-sf-accent: #0f766e; --200stack-sf-accent-hover: #115e59; --200stack-sf-text: #ecfdf5; --200stack-sf-muted: #a7f3d0; --200stack-sf-border: #2d6a5c; --200stack-sf-radius: 14px; --200stack-sf-surface: #06251f; --200stack-sf-error: #fb7185; --200stack-sf-error-surface: #4c0519; }

一般のサイトでは CSS の先頭に @layer static-forms; を置きます。レイヤー外の CSS と、後ろのレイヤーの CSS が勝ちます。Tailwind v4 では @layer theme, base, static-forms, components, utilities; を @import "tailwindcss"; より前に置き、@import '@200stack/static-forms-astro/theme.css'; と layer() なしで読み込みます。Astro は既定の build.inlineStylesheets: 'auto' で小さな CSS を inline にすることがあります。厳しい CSP では 'never' にしてください。

theme.css だけの本番は外部 CSS なので style-src 'self'(または配信元)で足りますが、v2 は固定の <style> を常に出します。本番は 'sha256-LE3mSYpIJxrT67iqOfLXzAcqron3YCrRA+rogsSVPYA='、開発表示は 'sha256-PooA9aoFhckRsEL2CK2Uxp0tODRwW2JydE6jQ+WgQ+M=' を style-src(指定時は style-src-elem にも)へ追加してください。開発表示の重複診断 style は出力ごとに hash が必要です。クラス指定を使う本番でも固定 style の hash は必要です。

0.1 からの移行

| 0.1 | 0.2 | | --- | --- | | 平たい label / description / error | field.label / .description / .error | | input / textarea / select | 種類ごとの .control | | fields.* / types.* の input | text 系は .control、radio・checkbox は .input | | 文字列の field / section / confirmation / completion | それぞれの .root | | choiceGroup / choiceLabel / radio / checkbox | radio / checkbox の .group / .option / .input | | sectionTitle / sectionDescription | section.title / .description | | confirmationList など | confirmation.list など | | types / fields | 種類キー / byName | | first / last | section 内の表示位置は CSS、特定項目は byName |

StaticFormElementClasses・StaticFormFieldClasses は削除済みで、項目の型は StaticFormFieldStyle です。旧キーは読み替えず、Static Forms style uses 0.1 key at fields.email; see README: Migrating from 0.1 のようにエラーになります。

送信の完了と計測

完了時はメッセージを表示するか、サイトのルートからのパス(例 /contact/thanks?from=contact)へ移動します。移動先は 2,048 字以内で、/ から始まる必要があります。//、絶対 URL、バックスラッシュ、空白・制御文字(0x00〜0x20、0x7f〜0x9f、U+2028・U+2029)、#、パスの .. 区間、エンコードされた .・/・バックスラッシュ(%2e・%2f・%5c、大文字も含む)は拒否します。クエリは使えます。移動先はページの URL を基準に解決し、同じ origin であることを確認します。

サンクスページはサイト側で用意してください。末尾のスラッシュはサイトのルーティングに合わせ、検索に載せたくない場合は noindex を設定してください。そのページの計測タグは、ページを直接開いた場合にも動きます。移動中は「移動しています…」(en: Redirecting…)を表示し、送信ボタンは無効のままです。移動の呼び出しが失敗した場合は、送信失敗とは区別した案内と手動リンクを表示します。location.assign を使うため、戻るボタンで入力済みの完了状態に戻れます(bfcache で保持された場合)。

受付が確認できた時点で、ルートから 200stack-static-form:accepted を通知します。bubbles: true・cancelable: false の CustomEvent です。message では完了要素を表示した後、redirect では移動を呼ぶ前に通知します。直接受付とポーリングの両方が対象です。確認できずにポーリングが時間切れになった場合や dispose 後には通知しません。

detail は通知ごとに作る凍結した { slotId?: string, publicFormId: string, instanceId: string } です。入力値・受付 ID・receipt・session は含みません。v2 の HTML には data-200stack-static-form-slot があり、SDK が渡した slotId を通知できます。属性がない旧い HTML では slotId のキーを省略します。v1 と開発表示にはこの属性を出しません。回数の保証は「同じ controller の同じ送信で最大 1 回」です。再読み込みや remount をまたぐ 1 回だけの保証はありません。イベントは偽造できるので、課金・権限付与などの受付証明には使えません。

STATIC_FORM_ACCEPTED_EVENT と StaticFormAcceptedEventDetail は core と adapter から export します。ブラウザで定数を使う場合は @200stack/static-forms-core/browser を使い、adapter の入口からは型だけを import してください。リスナーの Promise は待たず、通常の DOM リスナーの例外はブラウザが報告します。通知をキャンセルして完了処理を止めることはできません。

GTM と GA4 の例は どちらか一方 を使ってください。リスナーはサイト全体で 1 個とし、必要なら slotId で対象を絞ります。redirect で同じ成果をイベントとサンクスページの両方で数えないでください。移動前の通知は計測先への配送完了を保証しません。

計測は、サイトの Cookie の同意の管理(GTM・GA4 の同意モードなど)に従って送ってください。EU などでは計測に同意が要るのが一般的です。例は入力値を送りません。入力値を計測に足さないでください。

共有 layout の通常の <script> に一度置きます。Astro はこのスクリプトを処理して外部ファイルにまとめます。ClientRouter には引き続き対応しません。次は GTM の例です。

<script>
  import type { StaticFormAcceptedEventDetail } from '@200stack/static-forms-astro'
  const analytics = window as Window & {
    dataLayer?: Array<Record<string, unknown>>
    gtag?: (...args: unknown[]) => void
  }
  document.addEventListener('200stack-static-form:accepted', (event) => {
    const { slotId } = (event as CustomEvent<StaticFormAcceptedEventDetail>).detail
    if (slotId !== 'slot.contact') return
    analytics.dataLayer = analytics.dataLayer || []
    analytics.dataLayer.push({ event: 'static_form_accepted', form_slot: slotId })
  })
</script>

GTM ではカスタムイベント static_form_accepted をトリガーにし、GA4 イベントタグの名前を generate_lead、パラメーター form_slot を同名のデータレイヤー変数に設定します。GA4 を直接呼ぶ場合は、上の dataLayer の 2 行を次に置き換えてください(リスナーは追加しません)。

if (typeof analytics.gtag === 'function') {
  analytics.gtag('event', 'generate_lead', { form_slot: slotId })
}

CSP では処理後の共有 JS の配信元を script-src で許可します。is:inline などでインラインにする場合は hash または CSP と一致する nonce が必要です。GTM・GA 自体の配信元の script-src と送信先の connect-src なども別途許可してください。

開発中の表示

アプリの設定の「開発用トークン」でトークンを発行してください。発行・利用できるのは admin と developer です。Astro を実行するサーバー側の環境に、次を設定します。値は、開発用トークンの画面に出る環境変数の例に置き換えてください。STATIC_FORMS_DEV_ENVIRONMENT_ID には、アプリのデフォルトブランチの環境の ID が自動で入っているので、そのまま使ってください。表示されるのは、そのアプリに接続したフォームです(環境・ブランチごとには分かれません)。ローカルの画面に「環境・branch に対応する設置がありません。」と出たら、開発用トークンの画面で今の環境 ID を確かめ、STATIC_FORMS_DEV_ENVIRONMENT_ID を置き換えてください。

export STATIC_FORMS_DEV_ENABLED=1
export STATIC_FORMS_DEV_API_URL=https://dashboard.example.com
export STATIC_FORMS_DEV_TOKEN=sfdev_REPLACE_WITH_ISSUED_TOKEN
export STATIC_FORMS_DEV_APP_ID=app-id
export STATIC_FORMS_DEV_ENVIRONMENT_ID=environment-id
export STATIC_FORMS_DEV_BRANCH=feature/contact

API URL は HTTPS の origin を指定します。STATIC_FORMS_DEV_BRANCH はフォームの選び分けには使いません。作業中のブランチ名を入れておくと、保存データが別のブランチで取ったものでないかを確かめられます。branch を付けずに取った開発用のデータ(scope の branch が *)を使うときは * を入れてください。git からは推測しません。トークンを NEXT_PUBLIC_*・PUBLIC_* に入れないでください。

astro dev の StaticForm.astro は、公開版の入力を開発用プレビューとして表示します。送信はできず、送信用の controller script も出しません。取得に失敗した場合は フォームの位置に診断を表示します。

astro build や実行種別が不明の場合は開発 API を呼びません。ビルド用の入力・pin・STATIC_FORMS_BUILD_ONLY などがあれば、開発サーバーでも本番の入力を使います。入力が無ければエラーになります。

astro build を NODE_ENV=development で実行しないでください。開発表示には astro dev の command と import.meta.env.DEV の両方が必要です。build の出力に開発の印を含む HTML が残った場合も、ビルドを失敗にします。

API のデータを保存して使う場合は、プロジェクトのルートで次を実行します。

npx static-forms pull
export STATIC_FORMS_DEV_SNAPSHOT_PATH=.static-forms/development.json

既定の保存先は配信対象外の .static-forms/development.json です。更新には npx static-forms pull --force を使います。保存データにトークンは含まれません。

保存した snapshot は API より優先し、読み込みに失敗しても API に切り替えません。保存データを読む場合も、開発の有効化とアプリ・環境・STATIC_FORMS_DEV_BRANCH の設定は必要です。