Skip to main content

stacks-dashboard

Use when building or customizing the Stacks admin dashboard, including dashboard pages, model management views, analytics widgets, commerce dashboards, content management, settings panels, deployment monitoring, job/queue management, or the 401 built-in dashboard components. Covers the dashboard system at storage/framework/defaults/.

معلومات المصدر

المستودع
stacksjs/wildloop
آخر نشاط في المصدر
٢٤ سبتمبر ٢٠٢٦ في ٢٠:٥٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
stacks-dashboard
description
Use when building or customizing the Stacks admin dashboard, including dashboard pages, model management views, analytics widgets, commerce dashboards, content management, settings panels, deployment monitoring, job/queue management, or the 401 built-in dashboard components. Covers the dashboard system at storage/framework/defaults/.
license
MIT
compatibility
Bun >= 1.3.0, TypeScript
allowed-tools
Read Edit Write Bash Grep Glob
# Stacks Dashboard The Stacks admin dashboard provides a full-featured admin panel with 100+ route views, 401 components, and a multi-section layout. ## Key Paths - Dashboard components: `storage/framework/defaults/resources/components/Dashboard/` - Dashboard route views: `storage/framework/defaults/views/dashboard/` - Dashboard layouts: `storage/framework/defaults/views/dashboard/layouts/` - Dashboard actions: `storage/framework/defaults/app/Actions/Dashboard/` - Dashboard page endpoints: `storage/framework/defaults/routes/dashboard-api.ts` - Dashboard navigation registry: `storage/framework/defaults/resources/functions/dashboard/sidebar.ts` - Configuration: `config/ui.ts` ## Dashboard Sections Dashboard route views are mounted at the dashboard server root. Do not prefix page links with `/dashboard`. The `/api/dashboard/*` prefix is reserved for dashboard data Actions. ### Analytics and Monitoring - `/` - main dashboard overview - `/analytics` - analytics hub and chart navigation - `/analytics/web`, `/analytics/pages`, `/analytics/referrers` - HTTP analytics - `/analytics/countries`, `/analytics/devices`, `/analytics/browsers` - audience breakdowns - `/analytics/events`, `/analytics/blog`, `/analytics/marketing` - domain analytics - `/requests` - captured HTTP request metrics - `/errors`, `/monitoring/errors` - error tracking and analysis - `/jobs`, `/jobs/history` - background job monitoring - `/queue` - queue management and metrics - `/queries`, `/queries/slow`, `/queries/history` - query analysis ### Commerce - `/commerce/dashboard` - commerce overview - `/commerce/pos` - point of sale - `/commerce/products` - product management - `/commerce/orders` - order management and processing - `/commerce/customers` - customer profiles and history - `/commerce/payments` - payment tracking - `/commerce/coupons` - coupon and promotion management - `/commerce/gift-cards` - gift card management - `/commerce/categories`, `/commerce/manufacturers`, `/commerce/units` - catalog metadata - `/commerce/variants`, `/commerce/reviews`, `/commerce/taxes` - catalog operations - `/commerce/waitlist/products`, `/commerce/waitlist/restaurant` - waitlists - `/commerce/delivery` and `/commerce/delivery/*` - delivery, shipping, driver, and license management ### Content Management - `/content/dashboard` - content overview - `/content/posts` - blog post CRUD - `/content/pages` - page management - `/content/authors` - author profiles - `/content/categories` - content categorization - `/content/tags` - tag management - `/content/comments` - comment moderation - `/content/files`, `/content/blog`, `/content/seo` - files, blog operations, and SEO ### The file manager's two layers (stacksjs/stacks#2577) Worth knowing before adding anything to it, because the split is not obvious from the endpoints: - **Storage operations** map to a `StorageAdapter` method and go straight to the disk: list, upload, create folder, rename, visibility, duplicate, delete. - **Metadata** - favourites and tags - has nowhere to live on a disk (extended attributes do not survive a copy; S3 object metadata is set at write time, so starring a 2 GB video would rewrite 2 GB). It lives in `storage_items`, keyed by `(disk, path)`, written by `PUT /files/favorite` and `PUT /files/tags`. **The disk is authoritative and the table is advisory.** The listing comes from the disk and rows are joined onto it, so a path with no row is a file with nothing recorded - which is most files. Renames and deletes made THROUGH the dashboard reconcile eagerly (a folder is a prefix update, because moving a folder moves everything under it); a completed listing sweeps rows for paths it did not see, which is free because the walk already enumerated them. A TRUNCATED listing sweeps nothing - it has not proved a path is absent. A file renamed outside the dashboard loses its metadata, and that is by design: a rename and a copy-then-delete are the same two events to a bucket listing, so reconciling would be guessing. ### The media pipeline (stacksjs/stacks#2578) None of the three things an upload might need can happen inside the request: a transcode is minutes, a vision call is a round trip to a third party. So an upload dispatches and the dashboard shows state. - `storage_item_tasks`, one row per `(disk, path, kind)`, kind being `optimize` (images, via `ts-images`), `transcode` (video, via `ts-videos`) or `tag` (a vision model). They succeed and fail independently, which is why this is not a column on `storage_items` - a video whose transcode finished and whose tagging failed is a normal state. - `dispatchDashboardFileTasks` decides from the CONTENT TYPE what a file needs. Most uploads are documents and get nothing. A transcode waits for a video profile, because the ladder is derived from the source dimensions. - A dispatch failure is RECORDED, not thrown: a queue that is down leaves a visible failure rather than an upload that fails or a file that is silently never processed. - `runTask` owns the queued -> running -> done/failed transitions so the three jobs cannot disagree about them. It rethrows after recording, because the row and the queue answer different questions - the queue decides whether to retry, the row is what somebody looking at the file sees. - `POST /files/reprocess` re-runs everything, or the kinds you name. Derivatives are written back to the same disk under `.variants/<path>/`. The leading dot keeps them out of the listing, which skips hidden components - a folder of thirty derivatives beside every photo makes the browser useless. ### Remote commands (stacksjs/stacks#960) Running a configured operation on a configured host over SSH. Deliberately NOT a terminal: the request names a host KEY and a command KEY, both from `config/remote.ts`, so there is nothing to escape and no shell to reach. An interactive session is tracked separately - `Bun.spawn` has no PTY, and `ssh -tt` gives a remote one but cannot propagate a window resize. Four things make it safe to expose, and each is a rule to keep: - **Host keys are verified.** `StrictHostKeyChecking=yes` against the host's declared `knownHosts`. Do NOT reuse `sshExec` from `@stacksjs/ts-cloud` for anything long-lived: it disables host key checking on purpose, for boxes a minute old whose keys cannot be known. - **Hosts and commands come from config, never the request.** A `RemoteCommand` carries an `argv` ARRAY that is never interpolated. - **The routes do NOT use `guard()`.** That helper drops auth entirely under `APP_ENV=local|development|test`, which here would be an unauthenticated command runner on any dev machine on the network. They use `authenticatedGuard`, and `remote-routes.test.ts` asserts it. - **Authorization fails CLOSED.** The `run-remote-command` gate receives the host and command keys; with no gate defined, every run is refused. This is the opposite of the websocket authenticator in `@stacksjs/realtime`, which proceeds when none is installed. Runs are recorded before AND after - a run recorded only on completion loses the command that hung and the one whose process died with the box. The audit sink writes to the application log rather than the dashboard's own database, which is the thing an operator with dashboard access could edit. **There is no ffmpeg.** #2578 asked whether video was in scope given the external binary, its licensing and its provisioning; `@stacksjs/video` is built on `ts-videos`, which encodes itself, so that question was already answered. Tags go through `taggables` + `taggable_models` with `taggable_type = 'storage_items'` - the trait the CMS already uses. Do NOT declare a `belongsToMany` to the `Tag` model for this: `taggable_models.tag_id` resolves against `taggables`, which is a different table from `tags`. ### Data Management - `/data/dashboard` - data overview - `/data/users` - user management - `/data/subscribers` - subscriber management - `/data/teams` - team management - `/data/activity` - persisted activity - `/models`, `/models/{model}` - generic model registry and explorer - `/notifications/dashboard`, `/notifications/history` - notification operations ### Mail - `/inbox` - inbound messages from the configured mailbox provider - `/inbox/activity` - inbound and outbound delivery activity - `/inbox/captured` - outbound messages captured by the local log mail driver - `/inbox/settings` - mailbox display and behavior preferences Captured mail uses `GET /api/dashboard/email/captured` and `GET /api/dashboard/email/captured/{id}`. Read captures through the shared parser in `Actions/Dashboard/Email/captured-mail.ts`; do not scrape files in an STX component or duplicate the log-driver format. Render all inbound and captured HTML through `Email/EmailBodyPreview.stx`. It owns the sandboxed `srcdoc` iframe, restrictive content policy, and no-referrer boundary. Never inject message HTML into the dashboard document. ### Marketing - `/marketing/campaigns` - campaign management - `/marketing/lists` - email list management - `/marketing/social-posts` - social post management - `/marketing/reviews` - marketing review workflows ### Library - `/library/components` - component browser - `/functions` - function registry and scaffold - `/releases` - release management - `/packages`, `/dependencies` - package and dependency inspection ### Settings - `/settings` - typed `config/*.ts` browser and editor - `/settings/appearance` - dashboard appearance - `/settings/billing` - account billing - `/settings/mail` - mail configuration - `/environment` - environment summary - `/access-tokens` - access-token management - `/cloud`, `/dns`, `/mailboxes` - infrastructure-specific settings ### Deployments - `/deployments` - deployment history, deployment controls, the custom TypeScript deploy-script editor, and visibility-aware live terminal output - `/deployments/{id}` - one persisted Deployment model record The deployment page composes `DeploymentList`, `DeploymentTable`, `DeploymentPreviewDialog`, `DeployScript`, and `LiveTerminalOutput`. The Preview action first collects the environment and optional domain, then calls the guarded `POST /api/dashboard/deployments/preview` Action. That Action runs the native `buddy deploy --dry-run --json` planner and returns its versioned, non-mutating plan. The dialog renders the ordered operations and resolved sites before the user may continue to the separate real deployment confirmation. Script reads and atomic writes use `GET|PUT /api/dashboard/deployments/script`. The terminal uses `GET /api/dashboard/deployments/terminal` and pauses polling while the document is hidden. Do not create separate `/deployments/scripts` or `/deployments/live-terminal` pages. Deployment recovery uses `POST /api/dashboard/deployments/rollback/preview` followed by `POST /api/dashboard/deployments/rollback`. The preview must run the native `buddy deploy:rollback --dry-run` path successfully, and execution must re-run that preview, compare its revision, and require the typed target environment confirmation. Never implement rollback by editing release links, restarting services directly, or guessing a prior release from Deployment model rows. Deployment rows are application history. Preserved releases and activation are owned by ts-cloud. ### Operations control plane The Operations sidebar entry deliberately remains one item. Section navigation lives in `Dashboard/Operations/OperationsNavigation.stx`: - `/operations/changes` - unified change review, active work, release approvals - `/operations/scheduler` - registered task runs and persisted pause state - `/operations/recovery` - destinations, policies, recovery points, restore drills - `/operations/migrations` - model diff, schema effects, ledger reconciliation - `/operations/incidents` - native alerts, health rules, ownership, silence state - `/operations/audit` - append-only operator events and correlations Operational state belongs in the ts-cloud control plane initialized by `Operations/control-plane.ts`. Use its stores for durable operations, events, releases, approvals, alerts, backups, actors, and environments. Do not create a parallel dashboard-only JSON file or duplicate those entities in application models. Application domain records still follow the normal `app/Models` and `useApi` convention. Use dashboard Actions for aggregate operational views and guard every route in `dashboard-api.ts`. Every mutating operator action must resolve the authenticated actor and append or correlate a control-plane event. Use `trackOperatorOperation()` for bounded synchronous work and the native durable queue for long-running backup, restore, or provider work. Empty states must reflect real absence of configuration or events. Never seed operational pages with sample incidents, releases, backups, or health data. Migration execution must start from `previewPendingMigrations()`, audit the ledger against live schema effects, hash the reviewed plan, and recheck it immediately before `buddy migrate`. Only `reconcileMigrationLedger()` may repair provable ledger drift. Partial and unverifiable migrations require human review and must not be silently recorded. ### Utilities - `/health`, `/insights`, `/logs` - operational health and logs - `/servers`, `/serverless`, `/realtime` - runtime infrastructure - `/management/permissions` - RBAC management - `/kanban` - model-backed board management - `/ci`, `/buddy` - CI and Buddy workflows ## Dashboard Components (250+) ### Layout Components - `Navbar` - top navigation bar - `Sidebar` - fixed desktop side navigation provided by the STX runtime - `MobileSidebar` - responsive drawer around the same sidebar content - `DashboardLayout` - reusable layout wrapper ### UI Components - Buttons, Modals, Toasts, Alerts, Dropdowns - Tables with sorting, filtering, pagination - Forms with validation - Charts and analytics widgets - File upload components - Rich text editors ### Action controls - Use `Dashboard/UI/Button.stx` for every dashboard action. Do not add page-local primary, secondary, success, warning, or danger button styles. - The `primary` variant is the canonical Deployment `Deploy` treatment: `bg-gradient-to-b from-blue-500 to-blue-600`. - Keep native buttons only for controls whose visual state is their meaning, such as tabs, sort headers, color choices, and full-surface modal backdrops. - Use `variant="secondary"` for supporting actions and `variant="danger"` for destructive confirmation actions. - Use `tag="a"` whenever `href` is reactive, for example `<Button tag="a" :href="detailsPath()">Open details</Button>`. Server rendering cannot infer an anchor from a client-only reactive URL. - When a submit action lives in a shared Modal footer, give the form a stable `id` and associate the action with `<Button type="submit" form="form-id">`. Do not duplicate the footer inside the form or use script-driven submission. - Prefer component events and named slots over string callback props or `data-action` markers. A `data-action` attribute is only valid when an active host integration consumes that exact action. ### Feature Components - `ProductForm`, `ProductList`, `ProductVariants` - `OrderTable`, `OrderDetail`, `OrderStatusUpdate` - `UserTable`, `UserForm`, `UserProfile` - `PostEditor`, `PostList`, `PostPublish` - `CouponForm`, `CouponList` - `EmailCompose`, `EmailList`, `EmailDetail` - `DeploymentList`, `DeploymentTable`, `DeploymentDetail`, `DeployScript`, `LiveTerminalOutput` - `JobMonitor`, `QueueStatus` - `SettingsForm` (generic, used by all settings pages) ## Dashboard Actions Located in `storage/framework/defaults/app/Actions/Dashboard/`: - Settings actions - get and update typed settings - Commerce actions - CRUD operations for commerce models - Content actions - CRUD operations for content models - Data actions - persisted model records and metrics - Deployment actions - deploy, script, terminal, and history operations - Job actions - job records and metrics - Notification actions - notification records and delivery metrics - Request actions - captured request analytics ## Model Dashboard Integration Models with `dashboard: { highlight: true }` appear prominently: ```typescript defineModel({ name: 'Product', dashboard: { highlight: true }, // highlighted in dashboard traits: { useApi: { uri: 'products', routes: ['index', 'store', 'show', 'update', 'destroy'] } } }) ``` The `useApi` trait auto-generates REST actions and routes for the model. The generic model explorer discovers the model separately. It does not generate a custom dashboard page. Use a dashboard-scoped Action when a page needs an aggregate response or a purpose-built transport shape. Register it under `/api/dashboard/*` in `storage/framework/defaults/routes/dashboard-api.ts`. Sensitive reads and all writes must use the route file's `guard()` boundary so local development stays usable while non-local environments require authentication and an admin role. The dashboard dev server delegates `/api/*` requests to the Stacks router. It does not delegate root-level application API groups such as `/payments/*`. Dashboard pages must call a registered `/api/dashboard/*` Action instead of hard-coding the separate API server port. User-scoped payment data is the exception to the local no-auth guard: register it with `authenticatedGuard()` so the bearer token is required even on localhost. For stateful settings, persist through a model with `useApi` and explicit middleware, then expose a narrow dashboard Action for the page. Keep account identity fields read-only when their source of truth is `config/*.ts`. ### Dashboard API client Use the shared `dashboardApi()` client for every dashboard network request, including requests in stores and guest pages. Do not call `fetch()` directly from dashboard views, components, composables, or stores. The shared client adds the stored bearer token, same-origin credentials, JSON serialization, the double-submit CSRF header for mutations, and normalized response errors. Pass `auth: false` only for a deliberately public route such as password-reset or invitation-link lookup. This disables the bearer header, not CSRF protection. Keep the route path aligned with the registered Stacks route, for
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub