Skip to content

feat(playground): redesign provisioning frontend as command center - #32

Merged
Blind-Striker merged 1 commit into
masterfrom
feature/provisioning-command-center
Jul 9, 2026
Merged

Blind-Striker merged 1 commit into
masterfrom
feature/provisioning-command-center

Conversation

@Blind-Striker

Copy link
Copy Markdown
Member

📝 Description

What does this PR do?
Rebuilds playground/provisioning/LocalStack.Provisioning.Frontend from the untouched Blazor/Bootstrap template into a single-screen dark Command Center, matching the design language of the lambda playground's Command Center (#31):

  • Live SVG pipeline (Frontend → SNS → SQS → in-process handler → DynamoDB, plus a passive S3 node when the stack provisions a bucket) with sequential pulse animations as messages flow.
  • Event-driven UI: a MessageFlowNotifier singleton connects the publish action and the SQS ChatMessageHandler (which runs in the same process) to the UI — new messages appear in the feed instantly and the header shows measured publish-to-store latency; a 10 s reconciliation scan picks up external writes.
  • Real-state badges: SQS waiting count (ApproximateNumberOfMessages), handler in-flight count (ApproximateNumberOfMessagesNotVisible), DynamoDB item count — every number is read from the source, nothing resets on page refresh.
  • Demo tooling: "Simulate chat" publishes a scripted 10-message conversation through the real pipeline; a "slow handler" toggle (~2 s per message, poller concurrency lowered to 2) makes the queue backlog visibly build and drain.
  • Config drawer with stack outputs, LocalStack options, and corrected client endpoint display — fixes the misleading dynamodb.us-west-2.amazonaws.com text (from DetermineServiceOperationEndpoint, which ignores the LocalStack ServiceURL) and the empty SQS endpoint.
  • DynamoDB browser rework: table picker, raw attribute view with tooltips, auto-refresh with tab-hidden pause.
  • MapStaticAssets + fingerprinted assets replacing UseStaticFiles, fixing stale-CSS browser caching (no Cache-Control was sent).
  • Provisioning README updated; superpowers spec/plan working documents removed from docs/.

Both AppHosts (CDK and CloudFormation) keep working unchanged; healthcheck endpoints and AWS.Messaging configuration are untouched apart from the poller concurrency option.

Related Issue(s):

🔄 Type of Change

  • ✨ New feature (non-breaking change that adds functionality)
  • 📚 Documentation update
  • 🧹 Code cleanup/refactoring

🎯 Aspire Compatibility

  • Follows Aspire.Hosting.AWS patterns
  • Works with existing AWS integrations

🧪 Testing

How has this been tested?

  • Manual testing with playground examples
  • Tested with LocalStack container
  • Tested auto-configure (UseLocalStack())

Playwright-driven end-to-end verification on the CDK AppHost: publish → sequential pipeline pulses; instant feed insert (<2 s, event-driven); CLI put-item reconciliation within 10 s; queue backlog visibly building (0 → 6) and draining with the slow-handler toggle; config drawer endpoint correctness; zero console errors; no page-level horizontal overflow at 1512/1280/900 px. CloudFormation AppHost smoke-tested with the same frontend. Unit test suite: 486/486 passing. Build with warnings-as-errors: 0 warnings. Slopwatch: 0 issues.

Test Environment:

  • LocalStack Version: 4.12.0
  • .NET Aspire Version: 13.4.6
  • .NET Versions Tested: .NET 10 (playground)
  • Operating Systems: Windows 11

📚 Documentation

  • Code is self-documenting with clear naming
  • README.md updated (if needed)
  • Playground examples updated (if needed)

✅ Code Quality Checklist

  • Code follows project coding standards
  • No new analyzer warnings introduced
  • All tests pass locally
  • No merge conflicts
  • Branch is up to date with target branch
  • Commit messages follow Conventional Commits

🔍 Additional Notes

Breaking Changes: None — playground-only change; both AppHosts run unchanged.

Performance Impact: SQS GetQueueAttributes polled every 2 s and DynamoDB scanned every 10 s by the UI (demo-scale, LocalStack-local). Poller MaxNumberOfConcurrentMessages lowered to 2 for the backlog demo.

Dependencies: No new packages.

🎯 Reviewer Focus Areas

  • Aspire integration patterns
  • LocalStack compatibility

📸 Screenshots/Examples

Single screen: publish bar → live pipeline with real-state badges → chat feed + DynamoDB browser. Try it: run either provisioning AppHost, open the Frontend endpoint, enable "slow handler", hit "Simulate chat", and watch the queue badge climb and drain.


By submitting this pull request, I confirm that:

  • I have read and agree to the project's Code of Conduct
  • I understand that this contribution may be subject to the .NET Foundation CLA
  • My contribution is licensed under the same terms as the project (MIT License)

🤖 Generated with Claude Code

- Replace the Blazor template (Bootstrap, sidebar, 4 separate pages) with a
  single-screen dark Command Center sharing the lambda playground's design language
- Add MessageFlowNotifier: in-process events from the publish action and the SQS
  handler drive instant feed updates and sequential pipeline pulses; the header
  shows measured publish-to-store latency
- Render a live SVG pipeline (Frontend -> SNS -> SQS -> handler -> DynamoDB, plus
  passive S3 node when the stack provisions a bucket) with real-state badges:
  SQS waiting count, handler in-flight count, DynamoDB item count
- Add "Simulate chat" (scripted 10-message conversation through the real pipeline)
  and a "slow handler" demo toggle (~2s per message, poller concurrency 2) so queue
  backlog and drain become visible during bursts
- Add config drawer with stack outputs, LocalStack options, and corrected client
  endpoint display (LocalStack edge instead of the misleading regional AWS endpoint)
- Rework DynamoDB browser: table picker, raw attribute view, truncation with
  tooltips, auto-refresh with tab-hidden pause
- Switch to MapStaticAssets with fingerprinted assets, fixing stale-CSS browser
  caching caused by UseStaticFiles sending no Cache-Control
- Update the provisioning README for the new UI and remove the superpowers
  spec/plan working documents
@Blind-Striker
Blind-Striker requested a review from Copilot July 9, 2026 06:52
@Blind-Striker Blind-Striker self-assigned this Jul 9, 2026
@Blind-Striker Blind-Striker added this to the 13.4.0 milestone Jul 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR refactors the provisioning playground Frontend into a single-screen “Command Center” experience, adding live pipeline visualization and in-process UI updates while removing the older multi-page navigation UX.

Changes:

  • Introduces an in-process message flow notifier + demo toggles (slow handler) and wires them through the message handler and UI.
  • Replaces older pages/navigation with a Command Center home page and new panels (publish bar, pipeline, chat feed, DynamoDB browser, config drawer).
  • Overhauls the frontend styling/assets and updates provisioning README to describe the new UI.

Reviewed changes

Copilot reviewed 27 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
playground/provisioning/README.md Updates documentation to match the new Command Center UI and flows.
playground/provisioning/LocalStack.Provisioning.Frontend/wwwroot/js/visibility.js Adds a small JS helper for tab visibility detection.
playground/provisioning/LocalStack.Provisioning.Frontend/wwwroot/app.css Replaces the default styling with a dark Command Center theme and component styles.
playground/provisioning/LocalStack.Provisioning.Frontend/Services/TimeFormatting.cs Adds relative time formatting helper for message timestamps.
playground/provisioning/LocalStack.Provisioning.Frontend/Services/MessageFlowNotifier.cs Adds an in-process event hub for publish/store flow events used by UI.
playground/provisioning/LocalStack.Provisioning.Frontend/Services/EndpointDisplay.cs Adds UI-friendly endpoint display logic (LocalStack edge vs AWS regional).
playground/provisioning/LocalStack.Provisioning.Frontend/Services/DemoOptions.cs Adds demo runtime toggles shared between UI and handler (slow handler).
playground/provisioning/LocalStack.Provisioning.Frontend/Program.cs Registers new services, tweaks SQS poller concurrency, switches to static-assets mapping.
playground/provisioning/LocalStack.Provisioning.Frontend/Handlers/ChatMessageHandler.cs Adds slow-handler simulation and emits “stored” flow events to the notifier.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/_Imports.razor Adds new namespaces for Command Center components and services.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Shared/DynamoDBTableViewer.razor Reworks table viewer into a DynamoDB browser panel with auto-refresh and visibility pausing.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Routes.razor Removes FocusOnNavigate behavior from routing.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Pages/Home.razor Replaces the default home page with the Command Center layout and drawer toggles.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Layout/MainLayout.razor Simplifies layout to render the new single-screen experience without sidebar/nav.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/CommandCenter/PublishBar.razor Adds publish bar + scripted simulation + slow-handler toggle UI.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/CommandCenter/PipelinePanel.razor Adds live pipeline SVG with pulsing segments and queue depth badges.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/CommandCenter/MessagesPanel.razor Adds live chat message feed with reconciliation scanning and visibility pausing.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/CommandCenter/ConfigDrawer.razor Adds drawer to display AppHost stack outputs and client endpoints.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/App.razor Switches to static assets mapping and inline favicon; adds ImportMap usage.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Pages/MessagePublisher.razor Removes the legacy message publisher page in favor of the Command Center.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Pages/DynamoDBLocalTest.razor Removes the legacy DynamoDB test page in favor of the Command Center.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Pages/AppHostConfiguration.razor Removes the legacy AppHost configuration page in favor of the drawer.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Layout/NavMenu.razor Removes the legacy navigation menu.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Layout/NavMenu.razor.css Removes legacy nav menu styles.
playground/provisioning/LocalStack.Provisioning.Frontend/Components/Layout/MainLayout.razor.css Removes legacy layout/sidebar styles.
docs/superpowers/specs/2026-07-08-lambda-frontend-redesign-design.md Removes unrelated lambda redesign design doc from this PR’s diff.
docs/superpowers/plans/2026-07-08-lambda-frontend-redesign.md Removes unrelated lambda redesign implementation plan from this PR’s diff.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +30 to +39
internal sealed class MessageFlowNotifier
{
public event EventHandler<MessageFlowEventArgs>? FlowEvent;

public void NotifyPublished(string recipient) =>
FlowEvent?.Invoke(this, new MessageFlowEventArgs(MessageFlowStage.Published, recipient, null, null, DateTimeOffset.UtcNow));

public void NotifyStored(string messageId, string recipient, string message) =>
FlowEvent?.Invoke(this, new MessageFlowEventArgs(MessageFlowStage.Stored, recipient, message, messageId, DateTimeOffset.UtcNow));
}
Comment on lines +7 to +13
var reference = now ?? DateTimeOffset.UtcNow;
var seconds = Math.Round((reference - timestamp).TotalSeconds);

if (seconds < 5)
{
return "just now";
}
Comment on lines +1 to +3
export function isHidden() {
return document.hidden;
}
Comment on lines +80 to +91
private async Task<bool> IsTabHiddenAsync()
{
try
{
_visibilityModule ??= await Js.InvokeAsync<IJSObjectReference>("import", "./js/visibility.js");
return await _visibilityModule.InvokeAsync<bool>("isHidden");
}
catch (JSException)
{
return false;
}
}
Comment on lines +120 to 131
private async Task<bool> IsTabHiddenAsync()
{
if (string.IsNullOrEmpty(TableName))
try
{
HasError = true;
ErrorMessage = "TableName parameter is required";
IsLoading = false;
return;
_visibilityModule ??= await Js.InvokeAsync<IJSObjectReference>("import", "./js/visibility.js");
return await _visibilityModule.InvokeAsync<bool>("isHidden");
}
catch (JSException)
{
return false;
}

await RefreshAsync();
}
Comment on lines +124 to +132
try
{
var response = await DynamoDb.ScanAsync(new ScanRequest { TableName = _tableName });

var records = response.Items
.Select(ToRecord)
.OrderByDescending(record => record.Timestamp)
.Take(MaxItems)
.ToList();
Comment on lines 1 to 5
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>
@Blind-Striker
Blind-Striker merged commit 57c8fb8 into master Jul 9, 2026
5 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants