的特色表示還沒寫得夠白話,不放首頁。
#}
{% set features = [
("零建置",
"沒有 package.json、沒有 node_modules、沒有 watcher。stylesheet 在 fjkit 發佈時編譯,不在你的 app 執行時編譯。"),
("顏色只有一個開關",
"每個顏色都是 token。換品牌是改一個檔案,而且改完綠色仍然代表完成。"),
("掛在你現有的 API 上",
"每一個 htmx 端點都會用 JSON 回應 curl。同一條路由、同一個 handler、同一個回傳標註。"),
] %}
{% block content %}
{% call stack(8) %}
{% set intro %}
把 Jinja、Tailwind CSS 與 shadcn 風格元件整合起來,給 FastAPI 用。
{% endset %}
{{ page_header("給 FastAPI 的快速 UI", intro) }}
{{ defs("主要特色", features) }}
{# ============================================================== 01 #}
{% set i01 %}會寫後端、需要一套介面、不想碰前端工具鏈的人。{% endset %}
{% call lesson("who", "01", "給誰用", i01) %}
{% call prose() %}
適用對象:已經在寫 FastAPI,需要導覽、深色模式、一張可篩選的表格,
以及一個會驗證的表單。
要引入 React、Vue 或 Svelte 的專案不適用。這是設計決定,不是缺口。
{% endcall %}
{{ defs("預期成本", [
("第一頁", "約二十行 Python,含導覽與深色模式,沒有建置步驟"),
("一個後台畫面", "列表、篩選、新增表單與 htmx 更新,一個下午。不寫 CSS,也不寫 JavaScript。"),
("換品牌", "一份覆寫 token 的 stylesheet,掛在 kit 後面"),
("升級", "改一個版本號。stylesheet 在 wheel 裡,不在你的 repo 裡。"),
]) }}
{% endcall %}
{# ============================================================== 02 #}
{% set i02 %}一個 wheel、兩個執行期依賴,不需要自行編譯任何東西。{% endset %}
{% call lesson("box", "02", "wheel 裡裝了什麼", i02) %}
{% call grid(cols=2, gap=4) %}
{{ defs("套件裡帶的", [
("templates/ui/", "macro:版面、按鈕、資料、表單、表格、分頁、導覽、側欄、回饋、圖示與文件外殼"),
("static/dist/fjkit-.css", "編譯好的 stylesheet,每個風格包一份。234 KB 原始、23.9 KB gzip,在 build 自己守著的 28 KB 預算內。一頁只載一份。"),
("static/vendor/", "htmx 與 Basecoat 的 JavaScript,版本釘死,直接從套件裡供應"),
("1,767 個圖示", "Lucide,按名字內嵌。沒有 icon font、沒有 sprite 請求、執行期沒有 JS。"),
]) }}
{{ defs("你會用到的全部介面", [
("FjkitConfig、mount_fjkit", "接線,每支 app 一次"),
("@render", "在裝飾器上指名模板;handler 只回資料"),
("fjkit check", "詞彙表關卡。放進你的 CI。"),
("fjkit eject", "逃生口:把一支 macro 拿進你的 app 再改"),
]) }}
{% endcall %}
{% call prose() %}
需求:Python 3.13 以上,加上 FastAPI 與 Jinja2 兩個執行期依賴。
目前沒有加入第三個依賴的理由。
{% endcall %}
{% endcall %}
{# ============================================================== 03 #}
{% set i03 %}兩頁:一頁是接線,一頁是每一支 macro。{% endset %}
{% call lesson("next", "03", "接下來去哪", i03) %}
{% set n_learn %}kit 怎麼接、htmx 送出什麼,以及那個會讓 build 失敗的關卡{% endset %}
{% set n_components %}每支 macro 的實際渲染,附上產生它的那行呼叫{% endset %}
{{ defs("這個站上", [
("上手", n_learn),
("元件", n_components),
]) }}
{% endcall %}
{% endcall %}
{% endblock %}