gridkit
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Basarisiz
- Hardcoded secret — Potential hardcoded credential in .design/verify/typo.mjs
- eval() — Dynamic code execution via eval() in ci/browser-1105.js
- child_process — Shell command execution capability in ci/browser-1105.js
- fs.rmSync — Destructive file system operation in ci/browser-1105.js
- process.env — Environment variable access in ci/browser-1105.js
- fs module — File system access in ci/browser-1105.js
- child_process — Shell command execution capability in ci/browser-chart.js
- fs.rmSync — Destructive file system operation in ci/browser-chart.js
- process.env — Environment variable access in ci/browser-chart.js
- fs module — File system access in ci/browser-chart.js
- child_process — Shell command execution capability in ci/browser-column-toggle.js
- fs.rmSync — Destructive file system operation in ci/browser-column-toggle.js
- process.env — Environment variable access in ci/browser-column-toggle.js
- fs module — File system access in ci/browser-column-toggle.js
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Agent-ready PHP component framework for admin dashboards. Zero dependencies, Material Design 3, AJAX-first. 16 components, 1 CSS + 1 JS file.
GridKit
PHP components for admin dashboards. No build step, no dependencies, no JavaScript framework.
You write PHP. You get a searchable, sortable, filterable, paginated table that
reloads over AJAX — with themes, dark mode and a mobile layout you didn't have
to think about.

The whole CRUD table
Not a snippet — this is the complete file.
<?php
require_once '/path/to/gridkit/autoload.php';
use GridKit\Table;
(new Table('products'))
->query($db, "SELECT * FROM products ORDER BY name")
->search(['name', 'sku'])
->column('sku', 'SKU', ['width' => '120px', 'muted' => true])
->column('name', 'Product', ['sortable' => true])
->column('price', 'Price', ['format' => 'currency', 'sortable' => true])
->column('is_active', 'Status', ['format' => 'label'])
->button('edit', ['icon' => 'edit', 'modal' => 'edit_product'])
->button('delete', ['icon' => 'delete', 'confirm' => true])
->modal('edit_product', 'Edit', 'forms/product.php', ['size' => 'medium'])
->newButton('New product', ['modal' => 'edit_product'])
->paginate(25)
->render();
Search, sort, filter and paging run over AJAX. The edit button opens a modal
that loads forms/product.php. The delete button asks first, then firesgk:rowaction with the row's id — your application decides what deleting
means. The empty state knows whether the table is genuinely empty or just
filtered, and offers a way back.
table.addEventListener('gk:rowaction', e => {
const { action, params } = e.detail; // 'delete', { id: 42 }
});
A whole application
The snippet above is a table. This is what it looks like around one:

examples/invoices/ is a working invoice manager — list,
create, edit, delete, with search, filter, sort and paging answered by the
server over AJAX. English and German, its own strings loaded into GridKit's
catalogue with Lang::loadDir(). Around 700 lines across five files and alang/ directory, no database, no build step.
git clone https://github.com/mmollay/gridkit.git
cd gridkit && php -S localhost:8000
Then open http://localhost:8000/examples/invoices/. What each file does.
Install
composer require mmollay/gridkit
Composer puts GridKit under vendor/mmollay/gridkit/, and its css/ and js/
go with it. Layout::asset() stamps the path you hand it — it does not resolve
one — so hand it a path the browser can reach:
<link rel="stylesheet" href="<?= Layout::asset('vendor/mmollay/gridkit/css/gridkit.css') ?>">
<link rel="stylesheet" href="<?= Layout::asset('vendor/mmollay/gridkit/css/themes.css') ?>">
<script src="<?= Layout::asset('vendor/mmollay/gridkit/js/gridkit.js') ?>"></script>
If vendor/ sits outside your document root, copy or symlinkvendor/mmollay/gridkit/{css,js} into the public root and drop the prefix.
Or clone it — GridKit has no build step, so a checkout is a working install:
git clone https://github.com/mmollay/gridkit.git
mkdir -p my-app && cp gridkit/skeleton.php my-app/index.php
php -S localhost:8000
Then open http://localhost:8000/my-app/. skeleton.php is a working page:
sidebar, fixed header, theme switcher, content area, a table with a modal form,
assets wired up. It looks for GridKit beside itself, one directory up, and invendor/ — so the copy above works without editing anything. If you put it
somewhere none of those reach, it says so and tells you which line to change.
Requirements: PHP 8.2+ and a browser at Baseline 2023 — custom properties,
plus color-mix() (Chrome 111, Safari 16.2, Firefox 113), which the hover and
focus-ring tokens have quietly depended on for a long while; oklch() and
relative colour syntax sit behind @supports and degrade on their own.
No npm, no Composer plugins, no compilation. mbstring is used when present
but not required — bash ci/matrix.sh runs the suite on every PHP your machine
has and tells you which of them had it.
One thing the Composer package leaves out: the bundled CKEditor 5 build that
backs the rich-text form field. At 1.7 MB it would otherwise dominate every
install of a framework that advertises zero dependencies. A git clone includes it underassets/ckeditor5/ and the demo uses it; if you need the rich-text field from a Composer
install, include CKEditor yourself. Every other component works out of the box.
Six themes, light and dark
A theme is one hue. Colours are derived in OKLCH from that single value, so
every theme keeps the same lightness and the same contrast — white on the
primary surface measures between 4.69:1 and 5.73:1 across all six, so every
one of them clears WCAG AA rather than most of them.

[data-gk-theme="mint"] { --gk-theme-hue: 175; }
That is a complete seventh theme. Switching happens on <body>:
<body class="gk-root" data-gk-theme="ocean" data-gk-mode="dark">

Forms
Sixteen-column grid, validation, file upload with drag & drop, searchable
selects, rich text. Same fluent API as everything else.

(new Form('product'))
->field('sku', 'SKU', 'text', ['required' => true, 'width' => 4])
->field('name', 'Product', 'text', ['required' => true, 'width' => 12])
->field('notes', 'Notes', 'textarea', ['width' => 16])
->field('unit', 'Unit', 'select', ['options' => $units, 'width' => 6])
->field('pack', 'Pack size', 'text', ['width' => 6, 'showIf' => ['field' => 'unit', 'equals' => 'pcs']]) // only while the unit is pcs
->values($product) // fill every field from a record, by name
->errors($errors) // show a failed save's messages, by name
->render();
Built for AI agents
This is the part that makes GridKit different from other component libraries.
GRIDKIT_SKILL.md is a single structured document that
teaches any assistant — Claude, GPT, Gemini — the complete API: every
component, every option, code patterns, common recipes. Drop it into your
agent's project context and describe what you need:
"Build me a user management dashboard with roles and an invite flow."
The whole surface fits in one file an agent can actually read — every public
method of every component, named and shown. No scraping a docs site, no
guessing at method names, no hallucinated options.
What that is worth, measured. Five agents were given a page to build and
this file as their only source, the source tree off limits, four times over
twenty different tasks. On tasks the file had been corrected against, four of
five wrote a working page straight through. On tasks it had never seen, one of
five did — the rest needed a second or third pass, usually over something the
file did not say rather than something it said wrongly. Every run is in
CHANGELOG.md with the gaps it found.
That is the honest number, and it is the number this file is being written
against.
Three ways to give it to an assistant
# 1. Installed, for Claude Code — the assistant reads the rules first and
# fetches one reference on demand instead of all 61 KB.
cp -r skill ~/.claude/skills/gridkit
# 2. Fetched, for anything that can read a URL:
# https://gridkit.at/skill
# (llms.txt at the site root points there too)
# 3. Pasted: drop GRIDKIT_SKILL.md into the context. One file, no setup.
All three are the same content. skill/ is generated from GRIDKIT_SKILL.md
by ci/build-skill.sh, and a test fails if the two drift apart.
Components
Twenty-nine, each a PHP class with a chainable API:
Table — search, sort, filter, paginate, group, bulk actions, CSV export, rows that open a page or a side sheet, lists whose columns give way by their own width |
Form — 16-column grid, validation, upload, settings rows, answer tiles |
Modal — stackable, AJAX-loaded |
Sidebar — groups, badges, collapse, mobile overlay |
Header — fixed, search, user menu |
Button — filled, tonal, outlined, text, FAB |
StatCards — KPI tiles with trend, or compact tiles for a sheet |
Pagination — standalone or attached |
Select — searchable, multi, AJAX |
FilterChips — one-click filters |
TableHeader — unified filter bar |
PageSize — rows per page |
ActionGroup — grouped row actions |
SortLink — sortable headers |
YearFilter — year navigation |
BelegModal — document preview |
ImagePicker — choose one image from many: a compact grid, an enlarged view that can pick |
Tabs — every tab style and option, deep links, remembered tabs, lazy panels |
PermissionMatrix — roles × permissions: inheritance, locked roles, bulk toggles, one role at a time on a phone |
Tree — page trees, categories, folders: keys, selection, lazy branches, drag and drop |
LineItems — the lines of an invoice: live totals per VAT rate, the same in PHP to the cent |
Import — a CSV file into checked rows: columns matched to fields, a preview with every error, Excel's encoding, works without script |
DateRange — a period for reports and invoice lists: presets, two date fields, the period in words |
Calendar — a month of appointments: bars across days, "+3 more", an agenda on a phone, keys |
Chart — line, area, bar, donut and sparkline as SVG from the server: nice axes, numbers in the reader's language, a summary in words, the data as a table |
||
CommandPalette — Ctrl+K: pages, commands and records from your server, fuzzy, recent entries first |
FilterBuilder — conditions combined freely: AND/OR groups, saved views, the same tree as SQL with placeholders or as a row matcher, works without script |
Kanban — columns with cards: drag and drop, full keyboard moving, limits, saved with a way back, lanes on a phone |
FileManager — a media library and a receipt drawer: folders, thumbnails or a list, many uploads with progress, and a server check that trusts nothing an upload claims |
Plus Theme, Layout, Lang, Auth, Icon and Tooltip (the attributes and the
help icon of the tooltips, since 1.112.0) as infrastructure — and the
side sheet (.gk-sheet, GK.sheet), markup and script rather than a class: the
panel a row opens, docked beside the list, full screen on a phone. How a list
should look before its first row is written is in the skill's Six rules for
lists. The small parts an admin page used to style itself — status dots, avatar
colours, chart colours, settings rows, read-only fields, finger-sized buttons,
actions in a message — are classes since 1.92.0, so such a page needs no
stylesheet of its own. Two blocks are markup and classes as well: a timeline
(.gk-timeline, since 1.96.0) for a log of steps whose state is a symbol and a word,
and a portrait video frame (.gk-video-frame) for a 9:16 video or picture. A sortable
container (data-gk-sortierbar, js/sortierbar.js, since 1.97.0) lets a person put cards
or rows in order by dragging or by keyboard, and tells the server. The tree (Tree, since
1.116.0) brings a script of its own as well, js/tree.js, loaded the same way, and so do the CSV
import (Import, since 1.119.0): js/import.js, DateRange and Calendar (1.120.0): js/calendar.js, the charts
(Chart, since 1.121.0): js/chart.js, which adds the tooltip, the keys and the legend's switches to a chart that is
already complete without it, the command palette (CommandPalette, since 1.122.0): js/command-palette.js, the filter builder
(FilterBuilder, since 1.123.0): js/filter-builder.js, the kanban board (Kanban, since 1.124.0): js/kanban.js, which
adds dragging and keyboard moving to a board whose "Move to" forms already post without it, and the file manager
(FileManager, since 1.125.0): js/file-manager.js.
What GridKit is not
Honest boundaries, so you don't find out later:
- Not a full-stack framework. No routing, no ORM, no migrations. It renders
UI from data you already have. - Not a SPA. Pages are server-rendered PHP. AJAX updates fragments; it does
not manage client-side state. - Not a general-purpose design system. It is built for dense admin
interfaces — tables, forms, dashboards. - Small project, real use. GridKit runs production applications, but the
contributor base is one person. Read the code before you depend on it.
Tests
git clone https://github.com/mmollay/gridkit.git
cd gridkit && php tests/run.php
No Composer, no PHPUnit — the runner is sixty lines of plain PHP, because a
test suite that needed a package manager would contradict the first line of this
README. It renders every component and checks that the markup balances, that no
value reaches the page unescaped, and that the English locale contains no German.
The workflow in ci/ runs it on PHP 8.2, 8.3 and 8.4, plus one job withmbstring switched off. It is not active yet: it sits in ci/ rather than.github/workflows/ because the token this repository is pushed with has noworkflow scope. One git mv turns it on. A second workflow,ci/github-release.yml, creates the GitHub Release for every pushedv* tag from CHANGELOG.md (see ci/README.md).
Documentation
- Live demo — every component, switchable themes
- Example application — a CRUD app you can run in one command
- Agent skill — the complete API in one file
- Changelog — what changed and why
- Contributing — and the Code of Conduct
- Security policy — how to report a vulnerability privately
- Announcement drafts — what to post where, and in what order
License
MIT — see LICENSE.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi