Skip to content

Conversation

im2nguyen
Copy link
Collaborator

@im2nguyen im2nguyen commented Mar 11, 2025

🔗 Relevant links

This PR creates a new DevDot feature called "sandboxes". This extends the existing hosted terminal sessions (Instruqt) functionality across all of DevDot (tutorials and documentation).

Sandboxes let users experiment with our tools while navigating through our documentation. These sandboxes persist when users navigate to a different documentation page.

When users land on a tutorial that has an interactive lab, it will load the tutorial's interactive lab. However, they can override this behavior by opening the sandbox in the dropdown. They can re-load the tutorials' interactive lab by clicking "show terminal".

We also track sandbox behavior:

  • sandbox_start: URL and lab_id where users open the sandbox
  • sandbox_opened: URL and lab_id where the sandbox is open
  • sandbox_closed: URL and lab_id where user close the sandbox

Of these sandbox metrics, sandbox_start sends the highest signal on "I want to test this", with sandbox_opened showing potential pages where the sandbox is still useful during the user's learning journey.

Preview link 🔎: [Your preview link]
Asana task 🎟️: [Your task link]

🗒️ What

  • New sandboxes feature that provides persistent interactive terminals across DevDot
  • Enhanced error handling and monitoring with structured error tracking via PostHog
  • Improved user experience with toast notifications, loading states, and graceful error recovery
  • Robust component architecture with error boundaries and retry mechanisms
  • Comprehensive analytics tracking user sandbox interactions and error patterns

🤷 Why

  • Learning Enhancement: Users need hands-on experimentation while reading documentation
  • Persistence: Current tutorial labs don't persist across page navigation, breaking the learning flow
  • Reliability: The original implementation lacked comprehensive error handling, leading to poor UX when things went wrong
  • Monitoring: Need visibility into sandbox usage patterns and failure modes for continuous improvement
  • User Experience: alert() popups and silent failures created frustrating user experiences

🛠️ How

Core Sandboxes Implementation:

  • Extended Instruqt lab functionality to work across all DevDot pages
  • Added persistent state management using React context and localStorage
  • Implemented dropdown sandbox selector with override capabilities
  • Created dedicated sandbox pages for each product

Error Handling & Monitoring Enhancements:

  • Replaced all console.warn/console.error with PostHog error tracking
  • Added structured error categories: lab_launch_failed, configuration_invalid, storage_error, etc.
  • Implemented toast notifications instead of alert() popups
  • Added error boundaries with fallback UI components
  • Enhanced retry mechanisms for transient failures

Analytics Integration:

  • Comprehensive sandbox behavior tracking (start/opened/closed events)
  • Error monitoring with rich contextual data
  • User journey analysis capabilities

📸 Design Screenshots

[Add screenshots showing:]

  • Sandbox dropdown in navigation
  • Persistent sandbox while navigating pages
  • Loading states and error handling
  • Toast notifications vs old alert popups
Screen.Recording.2025-09-10.at.12.24.35.AM.1.mov

🧪 Testing

  • Unit Tests: Error boundary components, context providers, utility functions
  • Integration Tests: Sandbox persistence across page navigation
  • Error Scenarios: Network failures, configuration issues, storage problems
  • Accessibility: Screen reader compatibility, keyboard navigation
  • Build Validation: Zero TypeScript errors, ESLint compliance
  • Cross-browser: Tested in Chrome, Firefox, Safari, Edge

💭 Anything else?

Error Handling Philosophy:

  • All errors now provide actionable feedback to users
  • Development environments preserve detailed console logging
  • Production errors are tracked with sufficient context for debugging
  • Graceful degradation ensures features remain usable even when sandboxes fail

Future Considerations:

Copy link

vercel bot commented Mar 11, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
dev-portal Ready Ready Preview Comment Sep 16, 2025 2:29pm

Copy link

github-actions bot commented Mar 11, 2025

📦 Next.js Bundle Analysis

This analysis was generated by the next.js bundle analysis action 🤖

⚠️ Global Bundle Size Increased

Page Size (compressed)
global 299.21 KB (🟡 +50.19 KB)
Details

The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!

New Page Added

The following page was added to the bundle from the code in this PR:

Page Size (compressed) First Load
/[productSlug]/sandbox 179.94 KB 479.16 KB

Ninety-seven Pages Changed Size

The following pages changed size from the code in this PR compared to its base branch:

Page Size (compressed) First Load
/ 135.51 KB (🟡 +2.33 KB) 434.72 KB
/404 115.77 KB (🟡 +2.33 KB) 414.98 KB
/500 115.77 KB (🟡 +2.33 KB) 414.98 KB
/[productSlug]/docs 185.83 KB (🟡 +683 B) 485.04 KB
/[productSlug]/integrations 146.52 KB (🟡 +2.36 KB) 445.73 KB
/[productSlug]/integrations/[organizationSlug]/[integrationSlug] 170.38 KB (🟡 +2.94 KB) 469.59 KB
/[productSlug]/integrations/[organizationSlug]/[integrationSlug]/[integrationVersion] 170.38 KB (🟡 +2.94 KB) 469.59 KB
/[productSlug]/integrations/[organizationSlug]/[integrationSlug]/[integrationVersion]/components/[componentType]/[componentSlug] 180.08 KB (🟡 +2.94 KB) 479.29 KB
/[productSlug]/tutorials 149.9 KB (🟡 +2.35 KB) 449.11 KB
/[productSlug]/tutorials/[...tutorialSlug] 231.59 KB (🟡 +2.14 KB) 530.8 KB
/[productSlug]/tutorials/[collectionSlug] 197.01 KB (🟡 +2.94 KB) 496.22 KB
/_error 115.8 KB (🟡 +2.33 KB) 415.01 KB
/boundary 160.07 KB (🟡 +2.34 KB) 459.28 KB
/boundary/api-docs/[[...page]] 160.49 KB (🟡 +2.94 KB) 459.7 KB
/boundary/docs/[...page] 180.4 KB (🟡 +852 B) 479.61 KB
/boundary/install 179.14 KB (🟡 +2.34 KB) 478.36 KB
/certifications 176.93 KB (🟡 +2.92 KB) 476.14 KB
/certifications/[slug] 177.34 KB (🟡 +2.93 KB) 476.55 KB
/certifications/signin 176.64 KB (🟡 +2.92 KB) 475.86 KB
/consul 160.07 KB (🟡 +2.34 KB) 459.28 KB
/consul/api-docs/[[...page]] 180.4 KB (🟡 +851 B) 479.61 KB
/consul/commands/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/consul/docs/[...page] 180.4 KB (🟡 +852 B) 479.61 KB
/consul/install 172.63 KB (🟡 +2.34 KB) 471.84 KB
/consul/install/enterprise 172.66 KB (🟡 +2.34 KB) 471.88 KB
/hcp 160.07 KB (🟡 +2.34 KB) 459.28 KB
/hcp/api-docs/consul/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/api-docs/hvn/[[...page]] 157.2 KB (🟡 +2.82 KB) 456.41 KB
/hcp/api-docs/identity/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/api-docs/operations/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/api-docs/packer/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/api-docs/rbac/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/api-docs/vagrant-box-registry/[[...page]] 157.22 KB (🟡 +2.82 KB) 456.43 KB
/hcp/api-docs/vault-secrets/[[...page]] 155.67 KB (🟡 +2.89 KB) 454.89 KB
/hcp/api-docs/waypoint/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/api-docs/webhook/[[...page]] 157.21 KB (🟡 +2.82 KB) 456.42 KB
/hcp/docs/[...page] 180.39 KB (🟡 +852 B) 479.61 KB
/nomad 160.07 KB (🟡 +2.34 KB) 459.28 KB
/nomad/api-docs/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/nomad/commands/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/nomad/docs/[...page] 180.4 KB (🟡 +852 B) 479.61 KB
/nomad/install 172.11 KB (🟡 +2.34 KB) 471.32 KB
/nomad/install/enterprise 172.09 KB (🟡 +2.34 KB) 471.3 KB
/nomad/plugins/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/nomad/tools/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/open-api-docs-preview 161.5 KB (🟡 +2.66 KB) 460.71 KB
/open-api-docs-preview-v2/[[...page]] 160.62 KB (🟡 +3.05 KB) 459.83 KB
/packer 160.07 KB (🟡 +2.34 KB) 459.28 KB
/packer/docs/[...page] 180.4 KB (🟡 +856 B) 479.61 KB
/packer/guides/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/packer/install 172.08 KB (🟡 +2.34 KB) 471.3 KB
/profile/account 135.95 KB (🟡 +2.35 KB) 435.16 KB
/profile/bookmarks 136.96 KB (🟡 +2.35 KB) 436.17 KB
/sentinel 160.07 KB (🟡 +2.34 KB) 459.28 KB
/sentinel/docs/[...page] 180.4 KB (🟡 +854 B) 479.61 KB
/sentinel/install 172.08 KB (🟡 +2.34 KB) 471.3 KB
/terraform 160.07 KB (🟡 +2.34 KB) 459.28 KB
/terraform/cdktf/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/terraform/cli/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/terraform/cloud-docs/[[...page]] 180.41 KB (🟡 +853 B) 479.62 KB
/terraform/cloud-docs/agents/[[...page]] 180.41 KB (🟡 +850 B) 479.62 KB
/terraform/docs/[...page] 180.4 KB (🟡 +851 B) 479.61 KB
/terraform/enterprise/[[...page]] 180.4 KB (🟡 +854 B) 479.62 KB
/terraform/install 172.09 KB (🟡 +2.34 KB) 471.3 KB
/terraform/internals/[[...page]] 180.4 KB (🟡 +853 B) 479.62 KB
/terraform/intro/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/terraform/language/[[...page]] 180.4 KB (🟡 +854 B) 479.62 KB
/terraform/migrate/[[...page]] 180.4 KB (🟡 +854 B) 479.62 KB
/terraform/plugin/[[...page]] 180.4 KB (🟡 +852 B) 479.61 KB
/terraform/plugin/framework/[[...page]] 180.41 KB (🟡 +850 B) 479.62 KB
/terraform/plugin/log/[[...page]] 180.41 KB (🟡 +853 B) 479.62 KB
/terraform/plugin/mux/[[...page]] 180.41 KB (🟡 +853 B) 479.62 KB
/terraform/plugin/sdkv2/[[...page]] 180.4 KB (🟡 +851 B) 479.62 KB
/terraform/plugin/testing/[[...page]] 180.41 KB (🟡 +850 B) 479.62 KB
/terraform/registry/[[...page]] 180.4 KB (🟡 +854 B) 479.62 KB
/tutorials 127.19 KB (🟡 +2.33 KB) 426.4 KB
/tutorials/library 148.76 KB (🟡 +2.35 KB) 447.97 KB
/vagrant 160.07 KB (🟡 +2.34 KB) 459.28 KB
/vagrant/docs/[...page] 180.4 KB (🟡 +852 B) 479.61 KB
/vagrant/install 172.59 KB (🟡 +2.34 KB) 471.8 KB
/vagrant/install/vmware 172.09 KB (🟡 +2.34 KB) 471.3 KB
/vagrant/intro/[[...page]] 180.4 KB (🟡 +851 B) 479.61 KB
/vagrant/vagrant-cloud/[[...page]] 180.4 KB (🟡 +853 B) 479.61 KB
/validated-designs 122.29 KB (🟡 +2.33 KB) 421.5 KB
/validated-designs/[...slug] 177.64 KB (🟡 +822 B) 476.85 KB
/validated-patterns 152.68 KB (🟡 +2.35 KB) 451.9 KB
/validated-patterns/[...tutorialSlug] 191.18 KB (🟡 +1.66 KB) 490.39 KB
/validated-patterns/[collectionSlug] 137.27 KB (🟡 +2.35 KB) 436.48 KB
/vault 160.07 KB (🟡 +2.34 KB) 459.28 KB
/vault/api-docs/[[...page]] 180.4 KB (🟡 +853 B) 479.61 KB
/vault/docs/[...page] 180.4 KB (🟡 +853 B) 479.61 KB
/vault/install 172.08 KB (🟡 +2.34 KB) 471.29 KB
/vault/install/enterprise 172.09 KB (🟡 +2.34 KB) 471.3 KB
/waypoint 160.07 KB (🟡 +2.34 KB) 459.28 KB
/waypoint/docs/[...page] 180.4 KB (🟡 +852 B) 479.61 KB
/well-architected-framework 172.76 KB (🟡 +2.97 KB) 471.97 KB
/well-architected-framework/[...page] 180.41 KB (🟡 +849 B) 479.62 KB
Details

Only the gzipped size is provided here based on an expert tip.

First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.

Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis

Next to the size is how much the size has increased or decreased compared with the base branch of this PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this.

ritsok
ritsok previously approved these changes Sep 11, 2025
NavBar and SideBar are now utilizing the same functionality so developer has to update the token and url's in one location versus multiple.
Refactors sandbox lab ID handling to support both simple lab IDs (for direct launch) and full Instruqt track paths (for embedded scenarios).
This allows launching sandboxes from different contexts
and ensures the correct lab is launched based on the available information.

Updates the sandbox configuration to use the track name to retrieve the correct token and start the correct lab.
Adds `.env` to `.gitignore` file.
Simplifies Instruqt token retrieval by directly assigning default values.

This eliminates the dependency on environment variables for these tokens, streamlining the configuration process and making it more predictable.
Adds a document explaining how to update sandbox configurations and tokens.

This guide outlines the locations for updating track paths, scenarios, and tokens for the HashiCorp sandbox environments within the dev-portal project.
- Move tokens from config/base.json into sandbox.json instruqtTrack URLs
- Remove token definitions from base configuration
- Update sandbox configuration schema to validate tokens in URLs
- Update lab configuration interface to remove separate token field
- Simplify buildLabId to use complete instruqtTrack URL
- Update documentation to reflect new configuration pattern
- Remove separate token field from validateSandboxLab schema
- Update instruqtTrack URL pattern validation to include token parameter
- Align lab validation schema with unified token approach
- Fix test cases to validate correct URL format

This change completes the migration to embedding tokens directly in instruqtTrack
URLs, ensuring consistent validation across the sandbox configuration.
- Replace !! operator with Boolean() for type coercion in build-instruqt-url
- Move sandbox error boundary styles to CSS module
- Create sandbox-error-boundary.module.css
- Update components to use CSS module classes
- Maintain existing functionality and visual styles

These changes improve code quality by:
- Using explicit Boolean() constructor instead of double negation
- Following project conventions for CSS modules
- Removing inline styles for better maintainability
Updates `postcss` and `source-map` dependencies in `package.json` and `package-lock.json`.

Removes the unnecessary step of installing the latest npm version in the CI workflow, as the default npm version is sufficient.
Copy link
Collaborator

@RubenSandwich RubenSandwich left a comment

Choose a reason for hiding this comment

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

Looks great! 🚢

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.

9 participants