App Patterns

Common app interface pieces built from Bootstrap 3.3.7, the version cdn.ucsd.edu serves: tabs, side menus, toolbars and item bars, action menus, lists, pagination, dialogs, and responsive helpers. Each one has a live preview and a prompt you can copy. Further down: dashboard building blocks, seven complete app shells, and eight starter dashboards for campus areas.

Read the tags first

Bootstrap loads on every Decorator page, but the Decorator restyles only part of it. Each pattern carries one of these tags:

  • Decorator-styled The Decorator stylesheet already styles it. Use the markup as is.
  • Neutral Layout, gray borders, and link color only. Safe to use as is.
  • Brand layer Stock Bootstrap would paint it #337ab7 blue. Add the matching block from css/app-patterns.css, which re-colors it to the Decorator palette in the canvas only.
  • Bootstrap docs Not in the Decorator package. The markup comes from Bootstrap v3.3.7's own documentation source (twbs/bootstrap, tag v3.3.7, docs/_includes/).

Add the brand layer to a project

Run this once before you use any pattern tagged Brand layer.

Prompt

Add css/app-patterns.css to the project, copied from the Decorator Kit Developer Guide, and link it in the "site-specific CSS" block of each page that uses app patterns. Every rule must stay scoped under main#main-content plus an app-* class. Key active states on aria-current, aria-expanded, or :checked. Never target .active, .nav, .dropdown-menu, .btn-default, or any other class the header, navbar, or drawer uses.

Back to page index

Action bars and menus

Toolbar and item bar

A bar of grouped actions above a list or table. On the left: a selection count and bulk actions. On the right: an in-app search. Icon-only buttons need an aria-label.

Brand layerDropdown: Decorator-styled

.btn-toolbar.app-toolbarrole="toolbar".btn-group.btn.app-tool.input-group

Live preview

Prompt

Above the [requests table], add an item bar: div.btn-toolbar.app-toolbar with role="toolbar" and aria-label="[Request actions]". Contents, in order:
1. span.app-toolbar-count showing "[n] selected". Update it from js/[app].js and announce changes in an aria-live region.
2. A .btn-group of button.btn.app-tool: [Approve, Archive, Delete]. Icon-only buttons get aria-label.
3. A "More" dropdown (btn-group + dropdown-toggle + ul.dropdown-menu, following kitchen-sink/button_dropdowns.html) with [Export as CSV, Assign to…, Mark all as read].
4. A right-aligned form.app-toolbar-search with role="search": an .sr-only label, an input-group with input.app-search-input, and an icon submit button.
Include the toolbar block from css/app-patterns.css. Glyphicons only. This search filters the app, not the site. Leave the chrome search forms alone.

Sources: dist/kitchen-sink/icons.html (btn-toolbar), dist/kitchen-sink/button_dropdowns.html, dist/kitchen-sink/input_groups.html

Action menu (dropdown)

A compact menu of actions for one item or one page. The Decorator styles .dropdown-menu in navy with white links.

Decorator-styled

.btn-group.btn.btn-primary.dropdown-toggledata-toggle="dropdown"ul.dropdown-menuli.divider

Prompt

Add a "[New request]" dropdown button using the single-button dropdown from kitchen-sink/button_dropdowns.html, with btn-primary (not btn-success or others). Add aria-haspopup="true" and aria-expanded="false" to the toggle. Menu items: [..], then a li.divider with role="separator", then [..]. Don't add CSS for .dropdown-menu — the Decorator already styles it.

Source: dist/kitchen-sink/button_dropdowns.html

Back to page index

Lists and paging

Item list

Clickable rows with a title, a summary line, and a count or status. For inboxes, queues, and search results.

Brand layerBootstrap docs · list-group

.list-group.app-lista.list-group-item.list-group-item-heading.list-group-item-text.badge

Prompt

Render [requests] as a linked list group: div.list-group.app-list with one a.list-group-item per item, each holding h4.list-group-item-heading "[id · title]", p.list-group-item-text "[unit · date · status]", and an optional span.badge for unread counts. State status in words — don't use list-group-item-success/-info/-warning/-danger. Include the list and badge blocks from css/app-patterns.css. Escape all data before inserting it.

Media list (people, comments, activity)

An image or avatar beside a text block. For comment threads, activity feeds, and people pickers.

NeutralBootstrap docs · media

.media.app-media.media-leftimg.media-object.img-circle.media-body.media-heading

Live preview
  • Jordan Lee

    Facilities · 2 hours ago

    Plumber scheduled for tomorrow morning. The area is roped off.

  • Sam Rivera

    Requester · Yesterday

    Thanks! The sink on the 3rd floor has the same problem.

Prompt

Show the [comment thread] as a Bootstrap 3 media list (the markup from the Bootstrap docs' media example): ul.media-list with one li.media.app-media per entry, containing .media-left > img.media-object.img-circle (64 × 64, alt="" because the name is next to it) and .media-body with h4.media-heading [name], p.app-media-meta [role · time], and the text. Include the media block from css/app-patterns.css. Escape user text before rendering it.

Pagination

Page through long lists. Stock Bootstrap paints the current page #337ab7 and the links are only 34px tall. The brand layer re-colors them and makes each link a 44 × 44 touch target.

Brand layer

nav[aria-label]ul.pagination.app-paginationaria-current="page"

Live preview

Prompt

Add pagination under the [list] following kitchen-sink/pagination.html: nav aria-label="[Request pages]" > ul.pagination.app-pagination. Mark the current page with aria-current="page" on its link, not li.active. The previous/next links get aria-label ("Previous page", "Next page") with aria-hidden arrows. Include the pagination block from css/app-patterns.css.

Source: dist/kitchen-sink/pagination.html

Back to page index

Dialogs and disclosure

Modal dialog

A confirmation or short form that needs a decision before the user continues. modal.js handles focus, the Esc key, and the backdrop. Keep the modal markup inside the canvas.

NeutralBrand layer: headerBootstrap docs · js/modal

data-toggle="modal".modal.fade.app-modalrole="dialog"aria-labelledby.modal-dialog.modal-content

Live preview

Prompt

Expand and collapse

For FAQs and grouped details, use the Decorator drawer, which base.min.js already runs. Use Bootstrap's panel-group accordion only when you need its events.

Decorator-styled

.drawer-wrapper.drawer

Prompt

For the expandable [details] section, use the Decorator drawer (.drawer-wrapper > .drawer with h2 > a / div pairs, from templates/modules.html), not a Bootstrap panel-group accordion.

Back to page index

Helpers and responsive utilities

Responsive utilities

Show or hide content by breakpoint. Resize the window to see which chip shows. Bootstrap 3 breakpoints: xs <768px, sm ≥768px, md ≥992px, lg ≥1200px.

NeutralBootstrap docs · responsive-utilities

.visible-xs-inline-block.hidden-xs.visible-md-block.hidden-print

Live preview

You're on xs (phone) You're on sm (tablet) You're on md (laptop) You're on lg (desktop)

Prompt

On phones (xs), hide the [toolbar's text labels] with .hidden-xs and keep the icons. Every icon-only button needs an aria-label. Use Bootstrap 3 responsive utilities (visible-*-block/-inline/-inline-block, hidden-*). Don't write media queries for what these classes already do.

Helper class reference

Colorless Bootstrap helpers that are safe anywhere in the canvas, plus the ones to avoid.

Bootstrap 3.3.7 helper classes
ClassUse it forStatus
.sr-only, .sr-only-focusableText for screen readers only, such as labels for icon buttons and hidden form labelsSafe
.pull-left, .pull-right, .clearfixFloating a small element and clearing itSafe (not on the two-column split)
.center-block, .text-left/-center/-rightCentering blocks and aligning textSafe
.list-unstyled, .list-inlineRemoving bullets and inline link rowsSafe
.img-responsive, .img-rounded, .img-circleFluid images and avatarsSafe
.embed-responsive.embed-responsive-16by9A true 16:9 video box inside an app. Modules use .embed-videoSafe
.visible-*, .hidden-*, .hidden-printShowing and hiding by breakpoint, and for printSafe
.text-muted, .smallSecondary text (gray #777)Neutral. Check contrast
.text-*/.bg-* with -success/-info/-warning/-danger—Avoid: stock Bootstrap colors
.label-*, .progress-bar, .nav-pills active—Avoid, or add a canvas brand layer
title="" tooltips (tooltip.js)—Avoid: unreachable by keyboard and touch. Use visible help text

Prompt

Prefer Bootstrap 3.3.7 helper classes (sr-only, text-center, pull-*, clearfix, list-inline, img-circle, embed-responsive, visible-*/hidden-*) over new CSS. Don't use any -success/-info/-warning/-danger class, .label-*, .progress-bar, or title-attribute tooltips. Replace tooltips with a visible .help-block.

Back to page index

Dashboard building blocks

Six small pieces that almost every dashboard reuses. None needs a charting library. Each one shows its value as text, so it works without color and with a screen reader. The styles live in css/app-patterns.css.

Key number with trend

A headline number, what it measures, and how it changed. The arrow is decorative. The words "up" and "down" carry the meaning.

div.styledBrand layer

div.styled.app-stat.app-stat-value.app-stat-label.app-trend

Live preview
1,284 Tickets this month Up 6% from August
3.1h Median first response Down 20 min (better)
94% Satisfaction No change

Prompt

Add a row of [3] key numbers: .col-sm-4 columns, each a div.styled.app-stat with span.app-stat-value, span.app-stat-label, and span.app-trend. The trend is a Glyphicon arrow (aria-hidden) plus words: "Up 6% from August", "Down 20 min (better)", or "No change". Never show a trend by color alone. Include the KPI block from css/app-patterns.css.

Data bars

A labeled horizontal bar for comparing a few values: fill rate, occupancy, budget used. The number is printed beside every bar, and the bar itself is hidden from screen readers. For more than about 10 rows, or real charts, use a table or a charting library from canvas-components/.

Brand layer

ul.app-bars.app-bar-label.app-bar-track.app-bar-fill.app-w-[0–100].app-bar-value

Live preview

Residence hall occupancy

  • Revelle96%
  • Muir91%
  • Sixth77%
  • Seventh52%

Prompt

Show [occupancy by college] as data bars: a div.app-panel with p.app-panel-title, then ul.app-bars labelled by that title. Each li holds span.app-bar-label, span.app-bar-track (aria-hidden="true") containing span.app-bar-fill with the nearest 5% width class (app-w-0 … app-w-100), and span.app-bar-value with the exact number. Use .app-bar-attn to highlight a row, but say why in text too. No inline style widths — set the class from JS.

Status list

A list of named things, each with a status badge. Four states use only Decorator colors, and every state is spelled out in words.

Brand layerlist-group

.list-group.app-status-listspan.app-status[data-status="ok|warn|down|info"]

Live preview
  • Canvas LMS Operational
  • UCSD-PROTECTED Wi-Fi DegradedSlow connections in Geisel. Engineers are on site.
  • Print stations Outage
  • VPN Maintenance Sat 6 a.m.

Prompt

List [services] as ul.list-group.app-status-list. Each li.list-group-item has span.app-status-name, a span.app-status with data-status set to ok, warn, down, or info (a Glyphicon plus the words "Operational", "Degraded", "Outage", or "Maintenance [when]"), and an optional span.app-muted detail line. Don't use label-*, list-group-item-success/-warning/-danger, or any other Bootstrap contextual class.

Deadline timeline

What's coming up, in date order. Urgent items get a gold marker plus the word "urgent" for screen readers.

Brand layer

ol.app-timelineli[data-urgent].app-timeline-date.app-timeline-title

Live preview
  1. · 3 days (urgent)NIH R01 submissionDept. of Bioengineering · PI: Chen
  2. · 2 weeksNSF CAREER internal reviewOffice of Research Affairs
  3. · 5 weeksQuarterly effort certificationAll sponsored projects

Prompt

Show upcoming [deadlines] as ol.app-timeline in date order. Each li has span.app-timeline-date (a <time datetime> plus "· [time remaining]"), span.app-timeline-title, and span.app-muted context. Items due within [7] days get data-urgent and an .sr-only "(urgent)". Compute the time remaining in js/[app].js from the datetime values.

Checklist progress

A read-only list of steps with a summary line and a data bar. For onboarding, closeouts, and move-in. Use real checkboxes if people check items off on this screen.

Brand layer

ul.app-checklistli[data-done]ul.app-bars

Live preview

Onboarding: Alex Kim, Programmer Analyst

  • 3 of 5 done60%
  • Offer letter signed (done)
  • Background check cleared (done)
  • Active Directory account (done)
  • Cyber-security training (to do)
  • Parking permit (to do)

Prompt

Show [onboarding] progress in a div.app-panel: p.app-panel-title "[person, role]", a one-row ul.app-bars "[n] of [total] done", then ul.app-checklist. Done items get data-done, a glyphicon-check, and an .sr-only "(done)". Open items get glyphicon-unchecked and "(to do)". If people check steps off on this screen, use real labeled checkboxes instead.

Filter bar

Scopes the whole dashboard: term, unit, date range. Labels stay visible, and every control is at least 44px tall.

FormsBrand layer

form.app-filterbar.form-group.form-control.app-filter-control

Live preview

Prompt

Add a filter bar at the top of the dashboard: form.app-filterbar with aria-label="Dashboard filters". Each control is a .form-group with a visible label and a .form-control.app-filter-control: [Term select, College select, From date, To date], then a btn-primary "Apply". Keep the filters in the URL query string so views can be bookmarked, but never put personal data in it. Update the page from js/[app].js and announce "Showing [scope]" in an aria-live region.

Back to page index

Putting it together: app shells

Complete app screens, each combining several of the patterns above. Every shell has a live preview, the build order from top to bottom, and one prompt that builds the whole screen. Start from the closest one and change the placeholders.

Request manager

Template: blank-slate.html

Brand layerDecorator dropdown

Prompt

Create [requests.html] from blank-slate.html for a [request manager] app. Add it to the drawer and the navbar. Link css/app-patterns.css (copied from the Decorator Kit Developer Guide) in the site-specific CSS block.
Canvas, inside div.app-shell:
1. Item bar (div.btn-toolbar.app-toolbar, role="toolbar"): [New], bulk [Archive, Refresh] icon buttons with aria-labels, and a right-aligned in-app search form.
2. A .row: a .col-sm-3 side menu (nav > .list-group.app-sidemenu with [Inbox, Assigned to me, Closed] and badge counts, current item marked aria-current="page") and a .col-sm-9 work area.
3. In the work area: Bootstrap tabs (ul.nav.nav-tabs.app-tabs, role="tablist") for [Open, Due soon]. Each tab panel holds a .list-group.app-list of requests and a nav > ul.pagination.app-pagination.
4. A "Close request" modal (.modal.fade.app-modal) at the end of the canvas.
Load the data from [requests.json] in js/requests.js and escape every value. Use Bootstrap 3.3.7 data-api behaviors (tab, dropdown, modal, buttons) — no other JS framework. No -success/-info/-warning/-danger classes. Status is always written in words.

Operations dashboard

The at-a-glance home screen of an internal tool: headline numbers, what needs attention, and recent activity.

Template: blank-slate.html

  1. View header with a "last updated" line and a refresh button
  2. Four stat boxes (div.styled.app-stat) in a .row
  3. .msg.alert that appears only when something needs attention
  4. Two columns: a table.styled-dark of items due and a media list of recent activity

div.styled · .msg · table.styled-darkBrand layer

Live preview

Facilities Dashboard

Updated 9:41 a.m.
42Open requests
7Due today
3Overdue
1.8dAvg. time to close

3 overdue

Three requests are past their due date. Review overdue requests.
Due today
RequestBuildingStatus
RQ-1042GeiselIn progress
RQ-1051Price CenterNot started
RQ-1057RIMACWaiting on parts

Recent activity

  • Jordan Lee closed RQ-1039

    12 minutes ago

  • Sam Rivera opened RQ-1057

    1 hour ago

Prompt

Create [dashboard.html] from blank-slate.html for the [Facilities] dashboard. Add it to the drawer and the navbar. Link css/app-patterns.css.
Canvas, inside div.app-shell:
1. div.app-view-head with h4.app-view-title "[Facilities Dashboard]", an "Updated [time]" span.app-muted, and an icon refresh button (aria-label="Refresh dashboard").
2. A .row of four .col-xs-6.col-md-3 stat boxes, each a div.styled.app-stat with span.app-stat-value and span.app-stat-label: [Open requests, Due today, Overdue, Avg. time to close].
3. A .msg.alert only when overdue > 0, with a link to the overdue list.
4. A .row: .col-md-7 with a table.styled-dark.app-table "Due today" (caption, th scope="col", tr.even on alternate rows) and .col-md-5 with a ul.media-list of recent activity (li.media.app-media, avatar alt="").
Load data from [dashboard.json] in js/dashboard.js, escape every value, and announce refreshes in an aria-live region. Status is words, never color alone. No -success/-info/-warning/-danger classes, no progress bars.

Data admin table

Manage a list of records in bulk: select rows, act on them, switch views, and page through.

Template: blank-slate.html · for sorting and search at scale, swap in the DataTables widget

  1. View header with a primary "Add" action menu
  2. Item bar: selection count, bulk actions, view switcher, search
  3. table.styled-dark with a checkbox column (each with an .sr-only label)
  4. Row count and pagination

Dropdown · table.styled-darkBrand layer

Live preview

Room Inventory

Rooms
RoomBuildingSeatsStatus
107Geisel40Available
115Center Hall220Booked
2Price Center12Under repair
Showing 1–3 of 48 rooms

Prompt

Create [rooms.html] from blank-slate.html for a [room inventory] admin tool. Add it to the drawer and the navbar. Link css/app-patterns.css.
Canvas, inside div.app-shell:
1. div.app-view-head: h4.app-view-title "[Room Inventory]" and a btn-primary "Add" dropdown (dropdown-menu-right) with [Single room, Import from CSV].
2. Item bar (div.btn-toolbar.app-toolbar, role="toolbar"): span.app-toolbar-count "[n] selected", bulk [Edit, Export] app-tool buttons, a .btn-group.app-segmented radio filter [All, Available], and a right-aligned in-app search form.
3. table.styled-dark.app-table in .table-responsive: a first column of checkboxes, each with its own .sr-only label ("Select [room]"), and a "Select all" checkbox in the header. Columns: [Room, Building, Seats, Status]. Status in words. tr.even on alternate rows.
4. div.app-view-head with "Showing x–y of n" and nav > ul.pagination.app-pagination (aria-current="page").
In js/rooms.js: keep the selection count and "Select all" in sync, announce changes in an aria-live region, and escape every value. If sorting or search across more than ~200 rows is needed, use the DataTables widget (widgets/datatables.html) for the table instead.

Settings and profile

Sectioned preferences with a side menu, grouped form fields, and one save bar.

Template: two-column.html or blank-slate.html

  1. Side menu of settings sections (current one marked aria-current)
  2. Form grouped with fieldset/legend
  3. Segmented control for a single choice, checkboxes for toggles
  4. .app-savebar with Cancel / Save, and a .msg.info confirmation after saving

Forms · .msg.infoBrand layer

Live preview

Notifications

Saved

Your notification settings were updated.
Email me when
Digest frequency

Digests arrive at 7 a.m. Pacific.

Prompt

Create [settings.html] from [two-column.html] for the app's settings. Add "Settings" to the drawer, the navbar, and the side nav. Link css/app-patterns.css.
Canvas, inside div.app-shell, as a .row:
1. .col-sm-3: nav aria-label="Settings sections" > .list-group.app-sidemenu with a heading and [Profile, Notifications, Accessibility, Connected apps]. The current section gets aria-current="page".
2. .col-sm-9: h4.app-view-title for the section, then a form. Group related fields in fieldset.app-facet with a legend: checkboxes for on/off options, a .btn-group.app-segmented radio group for single choices, and .form-group/.form-control inputs with labels and autocomplete. Help text goes in .help-block, linked with aria-describedby.
3. div.app-savebar at the end: btn-default "Cancel" (reset) and btn-primary "Save changes".
After a successful save, show a .msg.info "Saved" above the form and move focus to it. Show validation errors above the form in a .msg.alert. Submit logic goes in js/settings.js, with a CSRF token.

Multi-step application

A longer form split into steps, with a visible step indicator and Back / Continue controls. For a full wizard with validation per step, use the Wizard widget.

Template: blank-slate.html · alternative: widgets/wizard.html

  1. Step indicator (ol.app-steps, with the current step marked aria-current="step" and completed steps named in text)
  2. The current step's fieldset
  3. Save bar with Back, Save draft, and Continue

FormsBrand layer

Live preview (static)

Research Funding Application

  1. Applicant (completed)
  2. Project
  3. Budget
  4. Review
Step 2 of 4: Project

250 words or fewer.

Prompt

Create [apply.html] from blank-slate.html for a [4]-step [funding application]. Link css/app-patterns.css.
Canvas, inside div.app-shell:
1. h4.app-view-title "[Research Funding Application]".
2. ol.app-steps with aria-label="Application progress" and one li per step: [Applicant, Project, Budget, Review]. The current step gets aria-current="step". Completed steps get data-state="done" plus an .sr-only "(completed)".
3. One fieldset.app-facet per step, with legend "Step n of 4: [name]" and Bootstrap 3 form fields (labels, autocomplete, help-block linked via aria-describedby). Show only the current step's fieldset.
4. div.app-savebar with btn-default "Back", btn-default "Save draft", and btn-primary "Continue" ("Submit" on the last step).
In js/apply.js: validate each step before advancing, show errors above the form in a .msg.alert, move focus to the new step's legend, and update aria-current. Save drafts to [endpoint] with a CSRF token. If the steps need branching or per-step validation UI, use the Wizard widget (widgets/wizard.html) instead.

Record detail

A single item's page: what it is, what happened to it, and what you can do next.

Template: two-column.html

  1. Breadcrumb back to the list (the template's breadcrumb, pointed at real pages)
  2. Header: title, status in words, and an Actions dropdown
  3. Tabs: Details (dl.dl-horizontal), Activity (media list plus a comment form), Files (item list)

Dropdowndl-horizontalBrand layer

Live preview

RQ-1042 · Leaking sink, Geisel 2nd floor

Status: In progress · Opened Sep 18 by Sam Rivera
Location
Geisel Library, 2nd floor east restroom
Category
Plumbing
Assigned to
Jordan Lee, Facilities
Due
September 23, 2026
  • Jordan Lee

    2 hours ago

    Plumber scheduled for tomorrow morning.

Prompt

Create [request-detail.html] from two-column.html as the detail view for one [request]. Set the breadcrumb to Home › [Requests] › [RQ-id], resolved from this page's folder. Link css/app-patterns.css.
Canvas, inside div.app-shell:
1. div.app-view-head: h4.app-view-title "[id · title]", a span.app-muted line with the status in words plus who opened it and when, and a btn-primary "Actions" dropdown (dropdown-menu-right) with [Reassign…, Change due date…, divider, Close request…]. "Close request…" opens a .modal.fade.app-modal confirmation.
2. Bootstrap tabs (ul.nav.nav-tabs.app-tabs, role="tablist"):
   - Details: dl.dl-horizontal.app-details with [Location, Category, Assigned to, Due].
   - Activity (with a count badge): ul.media-list of comments (li.media.app-media), then a comment form with a labeled textarea and a btn-default "Post comment".
   - Files: .list-group.app-list of attachments with a Glyphicon and size.
Load the record from [api/requests/:id] in js/request-detail.js. Escape all user text, and send comments with a CSRF token.

Search results for a catalog, directory, or knowledge base, with filter facets, a result count, and an empty state.

Template: blank-slate.html

  1. A large in-app search bar (not the site search)
  2. Filter facets as checkbox fieldsets in a side column
  3. Result count (announced to screen readers), a sort dropdown, and an item list
  4. Pagination and an empty state for zero results

Dropdown · formsBrand layer

Live preview
Level
Quarter

Prompt

Back to page index

Dashboards by campus area

Starter dashboards for the kinds of internal tools UC San Diego units build most often. Each one names who it's for and the data it touches, and combines the building blocks and patterns above. All names and numbers are made up.

Before you connect real data

Many of these dashboards show protected data: FERPA student records, personnel records, research budgets. Put them behind campus Single Sign-On, check authorization on every request, keep personal data out of URLs and logs, and treat anything you're unsure of as sensitive. Every prompt below includes these rules, so leave them in.

Build a dashboard with an agent, in four prompts

Don't ask for the whole app at once. Send these four prompts in order, and review the result of each before you send the next. Paste the dashboard prompt of your choice into step 2.

Step 1 · Scaffold

Create [dashboard.html] from blank-slate.html (from node_modules/ucsd-decorator-v5/dist/templates). Rewrite every CSS and script path to cdn.ucsd.edu. Add "[Dashboard name]" to the drawer and the navbar, leaving both search blocks as shipped. Copy css/app-patterns.css from the Decorator Kit Developer Guide and link it in the site-specific CSS block. Create an empty js/[dashboard].js and load it after base.min.js. Stop there, and show me the diff.

Step 2 · Static layout

Inside main#main-content only, build the static layout below using hard-coded sample data that is obviously fake. Use the Decorator and app-patterns classes named in it. No JavaScript yet.
[paste one dashboard prompt from the Developer Guide here]

Step 3 · Wire the data

In js/[dashboard].js, replace the sample data with data from [endpoint]. Keep the static markup as the no-JavaScript fallback where you can. Build DOM nodes with textContent (never innerHTML with data), set data-bar widths with app-w-* classes, and announce refreshes and filter changes in one aria-live region. The endpoint requires campus SSO. Handle 401/403 by showing a .msg.alert with a sign-in link, and handle empty results with an .app-empty state. Don't log response bodies.

Step 4 · Review and verify

Review [dashboard.html]:
- Did anything change outside main#main-content? Are all Decorator assets loaded from cdn.ucsd.edu?
- Any -success/-info/-warning/-danger, label-*, progress-bar, or title tooltips?
- One h1, headings in order, every status and trend written in words, 44px targets, visible focus, labeled inputs?
- No personal data in URLs, logs, or localStorage? SSO and authorization checked on every request?
Fix what you find, then run `npx ucsd-decorator-kit verify` and report the findings. Don't run --accept.
Student success · College advising

Advisor caseload

For: college academic advisors. Data: student records (FERPA), appointments, holds, early alerts.

Template: blank-slate.html

  1. Filter bar: term and college
  2. Four key numbers: caseload, appointments today, holds, early alerts
  3. Today's appointments table and an early-alert status list
Live preview

Advisor Caseload · Muir College

312Students assigned
9Appointments today
14Registration holds Down 5 this week
6New early alerts
Today's appointments
TimeStudentReason
9:00Student A.Major declaration
9:30Student B.Academic probation
10:15Student C.Study abroad

Early alerts

  • Student D.Missed 3 classes
  • Student E.Midterm below C
  • Student F.Advisor note

Prompt

Build an advisor caseload dashboard for [college] advisors in [advising.html], from blank-slate.html, with css/app-patterns.css. Canvas, inside div.app-shell:
1. h4.app-view-title "Advisor Caseload · [College]".
2. form.app-filterbar: Term and College selects, Apply.
3. Four div.styled.app-stat key numbers: Students assigned, Appointments today, Registration holds (with an .app-trend), New early alerts.
4. A .row: .col-md-7 has a table.styled-dark.app-table "Today's appointments" (Time, Student, Reason; each student name links to a detail view). .col-md-5 has a div.app-panel "Early alerts" with ul.app-status-list (status in words).
FERPA data: require campus SSO, and return only students assigned to the signed-in advisor, checked server-side on every request. No student IDs or names in URLs, logs, or browser storage. Show preferred names. Log access to student records for audit. Data comes from [endpoint], loaded in js/advising.js.
Academic affairs · Department scheduling

Course enrollment and waitlists

For: department schedulers and undergraduate coordinators. Data: section capacity, enrollment, and waitlists, all aggregate.

Template: two-column.html

  1. Quarter switcher (segmented control)
  2. Data bars: fill rate by course
  3. Waitlist table, sorted by pressure, with an export action
Live preview

Enrollment · Cognitive Science

Seats filled

  • COGS 1100% (full)
  • COGS 14A92%
  • COGS 10881%
  • COGS 18046%
Largest waitlists
CourseWaitlistCap
COGS 184400
COGS 14A31250
COGS 10812300

Prompt

Build a course enrollment dashboard for the [department] in [enrollment.html], from two-column.html, with css/app-patterns.css. Add it to the drawer, the navbar, and the side nav. Canvas, inside div.app-shell:
1. div.app-view-head: h4.app-view-title "Enrollment · [Department]" and a .btn-group.app-segmented quarter switcher [Fall, Winter, Spring].
2. A .row: .col-md-6 has a div.app-panel "Seats filled" with ul.app-bars per course (a full course gets .app-bar-attn, and the value text says "100% (full)"). .col-md-6 has a table.styled-dark.app-table "Largest waitlists" (Course, Waitlist, Cap), sorted by waitlist, then an .app-savebar with an "Export CSV" button.
Aggregate data only, with no student-level rows. Load it from [endpoint] per quarter in js/enrollment.js, and announce quarter changes in an aria-live region.
Research · Department research administration

Proposals and awards

For: department research administrators and PIs. Data: proposal pipeline, sponsor deadlines, award spending.

Template: blank-slate.html

  1. Pipeline data bars: proposals by stage
  2. Deadline timeline for the next 30 days
  3. Tabbed award table: Active, Ending soon
Live preview

Research Administration · Bioengineering

Proposal pipeline

  • Drafting12
  • Dept. review6
  • At OCGA4
  • Submitted20

Next 30 days

  1. · 3 days (urgent)NIH R01 · Chen
  2. · 2 weeksNSF CAREER · Patel
Active awards
AwardSponsorSpentEnds
Tissue scaffoldsNIH64%Jun 2027
Wearable sensorsDoD88% (ahead of plan)Dec 2026

Awards needing closeout or no-cost extension decisions.

Prompt

Build a research administration dashboard for [department] in [research.html], from blank-slate.html, with css/app-patterns.css. Canvas, inside div.app-shell:
1. h4.app-view-title "Research Administration · [Department]".
2. A .row: .col-md-6 has a div.app-panel "Proposal pipeline" with ul.app-bars per stage [Drafting, Dept. review, At OCGA, Submitted] showing counts. .col-md-6 has a div.app-panel "Next 30 days" with ol.app-timeline of sponsor deadlines (data-urgent within 7 days).
3. Bootstrap tabs (.app-tabs): "Active awards" and "Ending in 90 days" (with a count badge). Each is a table.styled-dark.app-table (Award, Sponsor, Spent %, Ends). Explain over- or under-spending in words.
Budget data is confidential: SSO, show only awards where the user is PI or a department admin (checked server-side), no amounts in URLs or logs. Data from [endpoint], in js/research.js.
Housing, Dining & Hospitality

Residence operations

For: residential life and operations staff. Data: occupancy by neighborhood, maintenance tickets, dining location status.

Template: blank-slate.html

  1. Key numbers: beds filled, open work orders, move-in checklist
  2. Occupancy data bars by college
  3. Dining locations status list
Live preview

Residence Operations · Fall move-in

15,240Beds filled Up 310 today
87Open work orders
4 of 6Move-in tasks done

Occupancy by college

  • Revelle97%
  • Warren95%
  • Eighth86%
  • Seventh66% (check-ins open)

Dining locations

  • 64 DegreesOpen
  • PinesLong line
  • Club MedClosed

Prompt

Build a residence operations dashboard in [housing.html], from blank-slate.html, with css/app-patterns.css. Canvas, inside div.app-shell:
1. h4.app-view-title "Residence Operations · [event]".
2. Three .col-sm-4 div.styled.app-stat: Beds filled (with an .app-trend), Open work orders, Move-in tasks done ("4 of 6").
3. A .row: .col-md-7 has a div.app-panel "Occupancy by college" with ul.app-bars for [Revelle … Eighth] (explain the highlighted row in its value text). .col-md-5 has a div.app-panel "Dining locations" with ul.app-status-list (Open / Long line / Closed).
Refresh every [5] minutes in js/housing.js and announce "Updated [time]" in an aria-live region, without moving focus. Aggregate data only — no resident names on this screen.
IT Services · Working example

Service status board

For: the service desk and anyone checking campus systems. Data: public service status. This one works: filter to issues, search by name, and the count updates for screen readers. The script is js/status-board.js, about 60 lines of plain JavaScript.

Template: blank-slate.html

  1. Key numbers: operational, degraded, outages
  2. Item bar: an All / Needs attention filter, search, and a live count
  3. Status list with detail lines, plus an empty state
Live preview · try it

Campus Service Status

Updated 9:41 a.m.
9Operational
2Degraded
1Outage
  • Canvas LMS Operational
  • UCSD-PROTECTED Wi-Fi DegradedSlow connections in Geisel Library. Engineers are on site.
  • Email and Calendar Operational
  • Print stations OutageCard readers offline campus-wide. Next update 11 a.m.
  • VPN Operational
  • Single Sign-On Operational
  • Zoom Operational
  • Library catalog DegradedSearches may time out. The vendor is investigating.
  • TritonLink Operational
  • Campus phones Operational
  • Research storage Operational
  • Concur Operational

Prompt

Build a campus service status board in [status.html], from blank-slate.html, with css/app-patterns.css, following the working example in the Decorator Kit Developer Guide (js/status-board.js). Canvas, inside div#its-board.app-shell:
1. div.app-view-head: h4.app-view-title "Campus Service Status" and an "Updated [time]" span.app-muted.
2. Three .col-xs-4 div.styled.app-stat counts: Operational, Degraded, Outage.
3. div.btn-toolbar.app-toolbar: a .btn-group.app-segmented radio filter [All, Needs attention], a span.app-live-count with role="status", and a right-aligned search form (.sr-only label).
4. ul.app-status-list with one li per service, carrying data-service and data-status, a status badge, and an optional detail line. Then a hidden div.app-empty.
Render the full list in HTML so it works without JavaScript. In js/status-board.js, filter by toggling Bootstrap's .hidden class. Listen for filter changes with jQuery ($(board).on('change', ...)), because button.js fires them through jQuery. Search on input. Update the count text on every change. Load statuses from [status feed] on an interval.
Facilities management · Sustainability

Energy and work orders

For: facilities managers and sustainability staff. Data: building energy use against targets, work orders by priority.

Template: blank-slate.html

  1. Filter bar: date range
  2. Key numbers with trends against last year
  3. Energy use against target as data bars, and a work-order tab set
Live preview

Energy & Work Orders · September

18.2GWh used Down 4% from last year
71%From on-site generation
243Open work orders Up 12 this week

Energy use against monthly target (top buildings)

  • Jacobs Hall108% (over)
  • Geisel Library92%
  • Price Center79%

Prompt

Build an energy and work-order dashboard in [energy.html], from blank-slate.html, with css/app-patterns.css. Canvas, inside div.app-shell:
1. h4.app-view-title "Energy & Work Orders · [period]" and a form.app-filterbar with From/To dates.
2. Three .col-sm-4 div.styled.app-stat with .app-trend compared to last year: GWh used, % from on-site generation, Open work orders.
3. A div.app-panel "Energy use against monthly target" with ul.app-bars for the top [10] buildings. Cap the bar at app-w-100 and say "[n]% (over)" in the value text when a building is over target.
4. Bootstrap tabs (.app-tabs) for work orders by priority [Emergency, Urgent, Routine]. Each is a table.styled-dark.app-table.
If a real chart is needed, add a charting library under canvas-components/ with its README, and keep the data table as the accessible alternative. Data from [endpoint], in js/energy.js.
UC San Diego Library

Study space availability

For: students (public view) and library staff. Data: room status, occupancy by floor, busy hours.

Template: blank-slate.html

  1. Floor switcher (segmented control)
  2. Room tiles with status words and a "Book" link
  3. Busy-hours data bars
Live preview

Geisel Study Rooms

Usually busy

  • 10 a.m.55%
  • 2 p.m.90% (peak)
  • 8 p.m.70%

Prompt

Build a study room availability page in [rooms.html], from blank-slate.html, with css/app-patterns.css. Canvas, inside div.app-shell:
1. div.app-view-head: h4.app-view-title "[Building] Study Rooms" and a .btn-group.app-segmented floor switcher.
2. A .row: .col-md-7 has ul.app-tiles with one li per room — the room name, a span.app-status in words ("Available", "In use until 3 p.m.", "Reserved at 2 p.m."), and for available rooms a "Book" link with .sr-only room context. .col-md-5 has a div.app-panel "Usually busy" with ul.app-bars by hour.
Students are anonymous on this page — show no booker names. "Book" goes to [booking system] and needs SSO there. Refresh statuses every [2] minutes in js/rooms.js and announce changes politely.
Human Resources · Department HR

New-hire onboarding tracker

For: department HR contacts and hiring managers. Data: personnel records and onboarding task status.

Template: two-column.html

  1. Side menu of new hires with progress counts
  2. The selected hire's checklist progress
  3. Upcoming start dates timeline (in the prompt; not shown in the preview)
Live preview

Alex Kim · Programmer Analyst · starts Oct 1

  • 3 of 5 done60%
  • Offer letter signed (done)
  • Background check (done)
  • Active Directory account (done)
  • Cyber-security training (to do)
  • Equipment request (to do)

Prompt

Build a new-hire onboarding tracker in [onboarding.html], from two-column.html, with css/app-patterns.css. Add it to the drawer, the navbar, and the side nav. Canvas, inside div.app-shell, as a .row:
1. .col-sm-3: nav aria-label="New hires" > .list-group.app-sidemenu with a heading "Starting soon" and one link per hire with a "[done]/[total]" badge. The selected hire gets aria-current="page".
2. .col-sm-9: a div.app-panel titled "[name] · [title] · starts [date]", a one-row ul.app-bars "[n] of [total] done", and ul.app-checklist (data-done plus .sr-only "(done)" / "(to do)").
3. Below it, a div.app-panel "Start dates" with ol.app-timeline (data-urgent for starts within 7 days where tasks are still open).
Personnel data: SSO, show only hires in the user's department (checked server-side), no names or employee IDs in URLs, and audit-log every view. Data from [endpoint], in js/onboarding.js.

Back to page index