# Teachfloor Docs > Complete documentation for Large Language Models --- ## Document: Teachfloor Developer Documentation URL: /home # Teachfloor Developer Documentation Build powerful integrations with the Teachfloor platform. Explore our guides, API reference, and SDKs to get started. --- ### Guides
API Guide Learn about authentication, rate limiting, and error handling. Webhooks Receive real-time event notifications from Teachfloor. Extension Apps Build custom apps that extend the Teachfloor platform. Teachfloor.js JavaScript SDK for custom frontend integrations.
### Reference & Resources
API Reference Interactive reference for all REST API endpoints. Blog Technical updates, tutorials, and platform news.
--- ## Document: /docs/README URL: /docs/README # Teachfloor Docs This repo is the **source of truth** for public documentation shown on **[docs.teachfloor.com](https://docs.teachfloor.com)**. --- ## Document: /docs/api URL: /docs/api # Teachfloor API REST API for integrating with the Teachfloor platform. ## Overview The Teachfloor Public API provides programmatic access to your organization's data, enabling you to build integrations, automate workflows, and extend the platform's functionality. **Base URL:** `https://api.teachfloor.com` ## Key Features - **RESTful design** - Standard HTTP methods (GET, POST, PUT, DELETE) - **JSON responses** - Easy to parse and work with - **Resource-oriented** - Predictable URL structure - **Comprehensive** - Access courses, members, activities, and more ## Quick Links - [Authentication](./api/authentication) - Get your API key - [Rate Limiting](./api/rate-limiting) - Usage limits - [Errors](./api/errors) - Error handling - API Reference - Interactive documentation at [docs.teachfloor.com](https://docs.teachfloor.com/api-reference) ## Getting Started 1. Generate an API key from your Teachfloor dashboard 2. Include it in the `Authorization` header 3. Make requests to the API endpoints ```bash curl https://api.teachfloor.com/v0/members \ -H "Authorization: Bearer YOUR_API_KEY" ``` ## Available Resources - **Activities** - Retrieve activity completion data - **Courses** - Manage courses and enrollments - **Members** - Access member information - **Custom Fields** - Work with custom field data See the full [API Reference](https://docs.teachfloor.com/api-reference) for complete endpoint documentation. ## Need Help? Contact support through your Teachfloor dashboard. --- ## Document: /docs/api/authentication URL: /docs/api/authentication # Authentication All API requests require authentication using an API key. ## How It Works Include your API key in the `Authorization` header using Bearer authentication: ``` Authorization: Bearer YOUR_API_KEY ``` ## Getting Your API Key 1. Log in to your Teachfloor account 2. Navigate to **Settings** → **Integrations** 3. Click **Generate API Key** 4. Copy and store the key securely **Security**: Never share your API key publicly or commit it to version control. ## Example Request ```bash curl https://api.teachfloor.com/v0/members \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" ``` ```javascript const response = await fetch('https://api.teachfloor.com/v0/members', { headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' } }); ``` ```php $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "https://api.teachfloor.com/v0/members", CURLOPT_HTTPHEADER => [ "Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json" ], ]); $response = curl_exec($curl); ``` ## Regenerating Your Key You can regenerate your API key at any time: 1. Go to **Settings** → **Integrations** 2. Click **Regenerate API Key** **Warning**: Regenerating invalidates the previous key. Update all applications using the old key. ## Best Practices - Store API keys in environment variables - Never hardcode keys in your application - Regenerate immediately if compromised ## Next Steps - [Rate Limiting](./rate-limiting) - Understand usage limits - [Errors](./errors) - Handle API errors --- ## Document: /docs/api/rate-limiting URL: /docs/api/rate-limiting # Rate Limiting The API enforces rate limits to ensure platform stability and fair usage. ## Rate Limit **50 requests per minute** per API key. ## Rate Limit Headers Each API response includes headers showing your current rate limit status: | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Maximum requests per minute (50) | | `X-RateLimit-Remaining` | Requests remaining in current minute | ## Example Response Headers ``` X-RateLimit-Limit: 50 X-RateLimit-Remaining: 42 ``` ## Exceeding the Limit If you exceed the rate limit, you'll receive: **Status Code:** `429 Too Many Requests` **Response:** ```json { "error": "Rate limit exceeded. Please try again later." } ``` ## Best Practices ### Monitor Remaining Requests ```javascript const response = await fetch('https://api.teachfloor.com/v0/members', { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }); const remaining = response.headers.get('X-RateLimit-Remaining'); console.log(`Requests remaining: ${remaining}`); if (remaining < 5) { // Slow down requests } ``` ### Implement Backoff ```javascript async function makeRequest(url) { try { const response = await fetch(url, { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }); if (response.status === 429) { // Wait 60 seconds and retry await new Promise(resolve => setTimeout(resolve, 60000)); return makeRequest(url); } return response; } catch (error) { console.error('Request failed:', error); } } ``` ### Batch Requests Optimize your API usage: - Cache responses when possible - Combine related data fetches - Use webhooks for real-time updates instead of polling ## Need Higher Limits? Contact support through your Teachfloor dashboard to discuss your use case. ## Next Steps - [Errors](./errors) - Handle API errors - [Authentication](./authentication) - API key setup --- ## Document: /docs/api/errors URL: /docs/api/errors # Errors Understanding and handling API errors. ## Error Response Format All errors return JSON with an `error` field: ```json { "error": "Error message describing what went wrong" } ``` ## HTTP Status Codes | Code | Meaning | Description | |------|---------|-------------| | `200` | OK | Request successful | | `400` | Bad Request | Invalid request parameters | | `401` | Unauthorized | Invalid or missing API key | | `403` | Forbidden | Authenticated but not authorized | | `404` | Not Found | Resource doesn't exist | | `429` | Too Many Requests | Rate limit exceeded | | `500` | Internal Server Error | Server error | ## Common Errors ### Invalid API Key **Status:** `401 Unauthorized` ```json { "error": "Unauthorized" } ``` **Solution:** Check your API key is correct and included in the `Authorization` header. ### Resource Not Found **Status:** `404 Not Found` ```json { "error": "Resource not found" } ``` **Solution:** Verify the resource ID exists and you have access to it. ### Rate Limit Exceeded **Status:** `429 Too Many Requests` ```json { "error": "Rate limit exceeded. Please try again later." } ``` **Solution:** Wait 60 seconds before retrying. See [Rate Limiting](./rate-limiting). ### Invalid Parameters **Status:** `400 Bad Request` ```json { "error": "Invalid parameters provided" } ``` **Solution:** Check your request parameters match the API documentation. ## Next Steps - [Authentication](./authentication) - API key setup - [Rate Limiting](./rate-limiting) - Usage limits --- ## Document: /docs/webhooks URL: /docs/webhooks # Teachfloor Webhooks Real-time event notifications from the Teachfloor platform. ## What Are Webhooks? Teachfloor uses webhooks to notify your application in real-time whenever specific events occur within your account. Instead of continuously polling the API for updates, webhooks push notifications directly to your system as events happen. ## How Webhooks Work When a subscribed event occurs, Teachfloor sends an HTTP POST request to your designated webhook endpoint with a JSON payload containing detailed information about the event. ### Common Use Cases - **Sync your database** - Keep records updated with course enrollments, completions - **Send notifications** - Alert users about important events - **Trigger workflows** - Automate processes based on platform events ## Quick Links - [Getting Started](./webhooks/getting-started) - Set up your first webhook - [Security](./webhooks/security) - Verify webhook signatures - [Delivery & Retries](./webhooks/delivery-retries) - Understanding webhook reliability - [Event Reference](./webhooks/event-reference) - Available webhook events - [Troubleshooting](./webhooks/troubleshooting) - Common issues and solutions ## Need Help? If you have questions or need assistance, contact support through your Teachfloor dashboard. --- ## Document: /docs/webhooks/getting-started URL: /docs/webhooks/getting-started # Getting Started Set up webhooks to receive real-time event notifications from Teachfloor. ## Prerequisites - Teachfloor account with access to Developers page - Publicly accessible HTTPS endpoint - Ability to process HTTP POST requests ## Setup Steps ### 1. Access Webhook Settings 1. Log in to your Teachfloor account 2. Navigate to **Developers** → **Webhooks** ### 2. Add Endpoint 1. Click **Add Endpoint** 2. Enter your HTTPS endpoint URL 3. Select which events to receive 4. Click **Save** ### 3. Get Signing Secret 1. Click **Reveal Signing Secret** on your endpoint 2. Copy and store the secret securely 3. Use this to verify webhook signatures ## Webhook Payload All webhooks have this structure: ```json { "id": "evt_abc123", "type": "course.join", "created_at": "2025-10-07T15:30:00.000000Z", "data": { // Event-specific data } } ``` ## Basic Implementation ```javascript app.post('/webhooks/teachfloor', express.json(), (req, res) => { // Respond immediately res.status(200).send('OK'); // Process async processWebhook(req.body).catch(console.error); }); ``` ```php Route::post('/webhooks/teachfloor', function (Request $request) { // Respond immediately response('OK', 200)->send(); // Process async ProcessWebhookJob::dispatch($request->json()->all()); }); ``` ## Requirements Your endpoint must: - Accept POST requests - Return 2xx status within 10 seconds - Verify signatures (see [Security](./security)) ## Next Steps - [Security](./security) - Verify signatures - [Delivery & Retries](./delivery-retries) - Understand reliability - [Event Reference](./event-reference) - View available events - [Troubleshooting](./troubleshooting) - Common issues --- ## Document: /docs/webhooks/security URL: /docs/webhooks/security # Security Verify that webhook events are genuinely sent by Teachfloor. ## Why Verify? Signature verification ensures: - Events are genuinely from Teachfloor - Payloads haven't been tampered with - Protection against malicious requests **Always verify signatures in production.** ## How It Works Teachfloor signs each webhook using HMAC-SHA256: ``` signature = hash_hmac('sha256', json_payload, secret) ``` The signature is sent in the `Teachfloor-Signature` header. ## Getting Your Secret 1. Go to **Developers** → **Webhooks** 2. Select your endpoint 3. Click **Reveal Signing Secret** 4. Store securely (never commit to version control) ## Implementation ### PHP ```php function verifyWebhookSignature(Request $request, string $secret): bool { $payload = $request->getContent(); $signature = $request->headers->get('Teachfloor-Signature'); $generated = hash_hmac('sha256', $payload, $secret); return hash_equals($generated, $signature); } Route::post('/webhooks/teachfloor', function (Request $request) { $secret = config('services.teachfloor.webhook_secret'); if (!verifyWebhookSignature($request, $secret)) { return response('Invalid signature', 401); } ProcessWebhookJob::dispatch($request->json()->all()); return response('OK', 200); }); ``` ### Node.js ```javascript const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const generated = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); return crypto.timingSafeEqual( Buffer.from(generated), Buffer.from(signature) ); } app.post('/webhooks/teachfloor', express.raw({ type: 'application/json' }), (req, res) => { const secret = process.env.TEACHFLOOR_WEBHOOK_SECRET; const signature = req.headers['teachfloor-signature']; const payload = req.body.toString('utf8'); if (!verifyWebhookSignature(payload, signature, secret)) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(payload); processWebhookEvent(event); res.status(200).send('OK'); } ); ``` ## Important Notes - Use raw request body (not parsed JSON) - Use timing-safe comparison (`hash_equals` or `timingSafeEqual`) - Store secrets in environment variables - Verify before processing ## Next Steps - [Delivery & Retries](./delivery-retries) - [Event Reference](./event-reference) - [Troubleshooting](./troubleshooting) --- ## Document: /docs/webhooks/delivery-retries URL: /docs/webhooks/delivery-retries # Delivery & Retries Understanding webhook reliability and retry behavior. ## How Delivery Works 1. Event occurs in Teachfloor 2. HTTP POST sent to your endpoint (10 second timeout) 3. Response checked 4. 2xx status = success, otherwise retry ## Successful Delivery Your endpoint must respond with 2xx status within 10 seconds: - `200 OK` (recommended) - `201 Created` - `202 Accepted` - `204 No Content` ## Retry Mechanism - **Total attempts**: 3 (initial + 2 retries) - **Timeout**: 10 seconds per attempt - **Backoff**: Exponential (10^attempt seconds) ### Retry Schedule | Attempt | Wait Time | Total Elapsed | |---------|-----------|---------------| | Initial | 0s | 0s | | 1st retry | 10s | 10s | | 2nd retry | 100s | 110s | ### When Retries Occur - Non-2xx status code - Timeout (>10 seconds) - Connection failure ## Handling Duplicates Every delivery carries a `Teachfloor-Idempotency-Key` header whose value is stable across retry attempts (it equals the envelope `id` field). Use it as your dedupe key — checking the header lets you short-circuit before parsing the body: ```javascript const processed = new Set(); function processWebhook(req) { const key = req.headers['teachfloor-idempotency-key']; // or event.id from the body if (processed.has(key)) return; processed.add(key); // Process event } ``` Retries carry the SAME key, so any 2xx you send after a retry-triggering timeout will still be treated as duplicate work on your side. ## Monitoring View delivery logs in your Teachfloor dashboard: 1. Go to **Developers** → **Webhooks** 2. Select your endpoint 3. Check delivery history ## Next Steps - [Event Reference](./event-reference) - [Security](./security) - [Troubleshooting](./troubleshooting) --- ## Document: /docs/webhooks/event-reference URL: /docs/webhooks/event-reference # Event Reference Complete reference of available webhook events. ## Event Structure All webhook events follow this JSON structure: ```json { "id": "evt_abc123", "type": "course.join", "created_at": "2025-10-07T15:30:00.000000Z", "data": { // Event-specific data } } ``` ### Root Fields | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique identifier for this webhook event | | `type` | string | The event type (e.g., `course.join`, `element.completed`) | | `created_at` | string | ISO 8601 timestamp when the event was created | | `data` | object | Event-specific payload (structure varies by event type) | ## Available Events ### Course Events #### `course.created` Triggered when a new course is created. #### `course.updated` Triggered when a course is updated. #### `course.completed` Triggered when a member completes a course. #### `course.join` Triggered when a member joins a course. **Payload example:** ```json { "id": "evt_abc123", "type": "course.join", "created_at": "2025-10-07T15:30:00.000000Z", "data": { "id": "cm_xyz789", "object": "course_member", "joined_at": "2025-10-07T15:30:00.000000Z", "member": { "id": "usr_123", "object": "member", "first_name": "John", "last_name": "Doe", "full_name": "John Doe", "avatar": "https://example.com/avatar.jpg", "email": "john@example.com", "is_email_verified": true, "last_seen": "2025-10-07T14:00:00.000000Z" }, "course": { "id": "crs_456", "object": "course", "created_at": "2025-01-01T00:00:00.000000Z", "name": "Introduction to Development", "status": "published", "cover": "https://example.com/cover.jpg", "availability": "public", "visibility": "listed", "start_date": null, "end_date": null, "currency": "USD", "price": 99.00, "free_label": null, "url": "https://app.teachfloor.com/org/intro-dev", "public_url": "https://app.teachfloor.com/org/intro-dev/join", "join_url": "https://app.teachfloor.com/org/intro-dev/join", "metadata": {}, "custom_fields": {} }, "custom_fields": {} } } ``` ### Module Events #### `module.created` Triggered when a new module is created. #### `module.updated` Triggered when a module is updated. ### Element Events #### `element.created` Triggered when a new element is created. #### `element.updated` Triggered when an element is updated. #### `element.deleted` Triggered when an element is deleted. #### `element.completed` Triggered when a member completes an element. **Payload example:** ```json { "id": "evt_def456", "type": "element.completed", "created_at": "2025-10-07T15:30:00.000000Z", "data": { "id": "act_789", "object": "activity", "timestamp": "2025-10-07T15:30:00.000000Z", "status": "completed", "passed": true, "score": 95, "completed_by": "usr_123", "member": { "id": "usr_123", "object": "member", "first_name": "John", "last_name": "Doe", "full_name": "John Doe", "avatar": "https://example.com/avatar.jpg", "email": "john@example.com", "is_email_verified": true, "last_seen": "2025-10-07T15:30:00.000000Z" }, "context": { "id": "elm_321", "object": "element", "created_at": "2025-01-01T00:00:00.000000Z", "name": "Introduction Video", "cover": "https://example.com/thumb.jpg", "type": "video", "position": 1, "module": "mod_654", "metadata": {} } } } ``` ### Member Events #### `member.login` Triggered when a member logs in. ## Object Types ### Member Object ```json { "id": "usr_123", "object": "member", "first_name": "John", "last_name": "Doe", "full_name": "John Doe", "avatar": "https://example.com/avatar.jpg", "email": "john@example.com", "is_email_verified": true, "last_seen": "2025-10-07T15:30:00.000000Z" } ``` ### Course Object ```json { "id": "crs_456", "object": "course", "created_at": "2025-01-01T00:00:00.000000Z", "name": "Course Name", "status": "published", "cover": "https://example.com/cover.jpg", "availability": "public", "visibility": "listed", "start_date": null, "end_date": null, "currency": "USD", "price": 99.00, "free_label": null, "url": "https://app.teachfloor.com/org/course-slug", "public_url": "https://app.teachfloor.com/org/course-slug/join", "join_url": "https://app.teachfloor.com/org/course-slug/join", "metadata": {}, "custom_fields": {} } ``` ### Element Object ```json { "id": "elm_321", "object": "element", "created_at": "2025-01-01T00:00:00.000000Z", "name": "Element Name", "cover": "https://example.com/thumb.jpg", "type": "video", "position": 1, "module": "mod_654", "metadata": {} } ``` ## Related Documentation - [Getting Started](./getting-started) - Set up your first webhook - [Security](./security) - Verify webhook signatures - [Delivery & Retries](./delivery-retries) - Understand reliability --- ## Document: /docs/webhooks/troubleshooting URL: /docs/webhooks/troubleshooting # Troubleshooting Common issues and solutions for webhooks. ## Not Receiving Webhooks **Check:** - Endpoint URL is correct and accessible - SSL certificate is valid - Events are selected in webhook settings - Firewall allows incoming HTTPS traffic - Endpoint returns 2xx status code **Test your endpoint:** ```bash curl -X POST https://your-endpoint.com/webhooks/teachfloor \ -H "Content-Type: application/json" \ -d '{"test": true}' ``` ## High Retry Rate **Causes:** - Endpoint not responding with 2xx status - Response taking longer than 10 seconds - Application errors during processing - Infrastructure issues **Solutions:** - Respond with 2xx immediately (before processing) - Move processing to background jobs - Fix application errors - Check server logs for issues ## Signature Verification Fails **Check:** 1. Using correct secret for this endpoint 2. Using raw request body (not parsed JSON) 3. No middleware modifying the body 4. Correct character encoding (UTF-8) **Debug:** ```javascript console.log('Received signature:', req.headers['teachfloor-signature']); console.log('Payload length:', payload.length); console.log('Generated signature:', generatedSignature); ``` ## Timeouts **Causes:** - Synchronous processing before responding - Slow database queries - External API calls before sending response **Solution:** ```javascript // Correct - respond immediately app.post('/webhooks', (req, res) => { res.status(200).send('OK'); processAsync(req.body); }); // Wrong - may timeout app.post('/webhooks', async (req, res) => { await processEvent(req.body); res.status(200).send('OK'); }); ``` ## Duplicate Events **Cause:** Webhooks may be delivered more than once due to retries. **Solution:** Use `event.id` for deduplication: ```javascript const processed = new Set(); function processWebhook(event) { if (processed.has(event.id)) return; processed.add(event.id); // Process event } ``` ## Viewing Delivery Logs Check webhook delivery history: 1. Go to **Developers** → **Webhooks** 2. Select your endpoint 3. View delivery log The log shows: - Timestamp of each attempt - Response status code - Response time - Error details ## Need Help? Contact support through your Teachfloor dashboard. --- ## Document: /docs/apps URL: /docs/apps # Teachfloor Apps Welcome to the Teachfloor App Development documentation! This guide will help you build powerful extensions that integrate seamlessly with the Teachfloor platform. ## What are Teachfloor Apps? Teachfloor Apps are extensions that enhance the platform's functionality by adding custom user interfaces, integrations, and workflows. Apps can: - Display custom UI components in various locations throughout the dashboard - Store and retrieve data securely - Access platform resources through permissions - Integrate with external services - Enhance the learning experience for instructors and learners ## Documentation Structure ### Getting Started 1. [Introduction](./apps/introduction) - Overview and concepts 2. [Quickstart Guide](./apps/quickstart) - Build your first app in 10 minutes ### Core Concepts 3. [App Manifest](./apps/core-concepts/app-manifest) - Configure your app's metadata and capabilities 4. [Viewports System](./apps/core-concepts/viewports) - Understand where apps can display 5. [Surfaces](./apps/core-concepts/surfaces) - How your app renders — drawer or widget — and how it pairs with viewports 6. [Extension Kit Components](./apps/core-concepts/extension-kit/components) - Use pre-built UI components 7. [Extension Kit Integration](./apps/core-concepts/extension-kit/integration) - Interact with the platform ### Advanced Topics 8. [Data Storage](./apps/advanced-topics/data-storage) - Persist user and app data 9. [Realtime Channels](./apps/advanced-topics/realtime) - Subscribe to and publish low-latency events between learners 10. [Webhooks](./apps/advanced-topics/webhooks) - Receive signed HTTP deliveries to your app's backend when platform events fire 11. [OAuth](./apps/advanced-topics/oauth) - Call the public API from your app's backend on behalf of the installing organization 12. [Permissions](./apps/advanced-topics/permissions) - Request and use platform resources 13. [Deployment](./apps/advanced-topics/deployment) - Deploy private apps and publish to marketplace ### Reference 14. [CLI Commands](./apps/references/cli) - Complete command reference 15. [Best Practices](./apps/references/best-practices) - Tips and patterns 16. [Examples](./apps/references/examples) - Sample apps and code snippets 17. [Troubleshooting](./apps/references/troubleshooting) - Common issues and solutions ## Prerequisites Before you begin, ensure you have: - Node.js 18.0.0 or higher - npm or yarn package manager - A Teachfloor account - Basic knowledge of React and JavaScript ## Support - **Issues**: [GitHub Issues](https://github.com/teachfloor/docs/issues) - **Email**: support@teachfloor.com ## License This documentation is provided under the MIT License. --- **Ready to get started?** Begin with the [Introduction](./apps/introduction) or jump straight to the [Quickstart Guide](./apps/quickstart)! --- ## Document: /docs/apps/introduction URL: /docs/apps/introduction # Introduction to Teachfloor Apps Teachfloor Apps are powerful extensions that allow you to customize and enhance the Teachfloor learning platform. Built using modern web technologies, apps integrate seamlessly into the platform's interface while maintaining security and performance. ## What Can You Build? ### UI Extensions Add custom interface components throughout the Teachfloor dashboard: - Sidebar widgets for quick access - Course-specific tools - Custom settings pages - Analytics dashboards - Productivity tools ### Data Applications Create apps that store and manage data: - Note-taking apps - Task managers - Progress trackers - Custom reports ### Backend Integrations (No UI Required) Build apps that run in the background without any user interface: - Event tracking to analytics platforms (Segment, Mixpanel) - User activity sync to CRM systems (Intercom, HubSpot) - Learning data export to data warehouses - Automated notifications and webhooks - Third-party API integrations ### Full-Stack Integrations Combine UI and backend capabilities: - Communication tools (Slack, Discord) - AI assistants with chat interfaces - Custom analytics with dashboards - Content recommendation engines ## Architecture ### Three Core Components ``` ┌─────────────────────────────────────────────────────┐ │ Teachfloor CLI │ │ Command-line tool for app development & deployment │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ Extension Kit Library │ │ React components & utilities for building UIs │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ │ Teachfloor Platform │ │ Hosts apps, manages permissions, serves SDK │ └─────────────────────────────────────────────────────┘ ``` ### How Apps Run Apps run in sandboxed environments within the Teachfloor dashboard: 1. **Isolation**: Each app runs in its own sandbox for security 2. **Communication**: Apps communicate with the platform via PostMessage RPC 3. **Context**: Platform provides user, organization, and environment data 4. **Storage**: Secure data persistence through the Extension Kit ``` ┌──────────────────────────────────────────────┐ │ Teachfloor Dashboard (Parent) │ │ ┌────────────────────────────────────────┐ │ │ │ Your App (Sandboxed) │ │ │ │ │ │ │ │ ┌──────────────────────────────┐ │ │ │ │ │ React Components │ │ │ │ │ │ (Extension Kit) │ │ │ │ │ └──────────────────────────────┘ │ │ │ │ ↕ │ │ │ │ ┌──────────────────────────────┐ │ │ │ │ │ Teachfloor SDK │ │ │ │ │ │ (PostMessage RPC) │ │ │ │ │ └──────────────────────────────┘ │ │ │ └────────────────────────────────────────┘ │ └──────────────────────────────────────────────┘ ``` ## Key Concepts ### App Manifest The manifest is a JSON configuration file that defines your app: ```json { "id": "unique-app-id", "version": "1.0.0", "name": "My Awesome App", "description": "Enhance your workflow", "distribution_type": "public", "ui_extension": { "views": [ { "viewport": "teachfloor.dashboard.course.list", "component": "CourseListView" } ] }, "permissions": [ { "permission": "courses:read", "purpose": "Display course information" } ] } ``` ### Viewports Viewports define where your app can display within the platform. Each viewport corresponds to a specific page or section, such as course pages, settings, community areas, and more. :::info See [Viewports System](./core-concepts/viewports) for the complete list of available viewports and their usage. ::: ### Extension Context Apps receive real-time context from the platform: ```javascript { userContext: { id: "user-123", full_name: "John Doe", email: "john@example.com", avatar: "https://...", language: "en", timezone: "America/New_York" }, appContext: { id: "app-456", name: "My Awesome App" }, environment: { initialized: true, viewport: "teachfloor.dashboard.course.list", path: "/org/courses" } } ``` ### Permissions Apps must request permissions to access platform resources: - `user:read`: Read user information - `courses:read`: Access course data - `modules:read`: Access module content - `elements:read`: Access learning elements - `user_events:read`: Track user activity ## Development Workflow ``` 1. Install CLI ↓ 2. Authenticate ↓ 3. Create App ↓ 4. Add Views & Components ↓ 5. Request Permissions ↓ 6. Test Locally ↓ 7. Build & Upload ↓ 8. Submit for Review ↓ 9. Publish to Marketplace ``` ## Distribution Models ### Private Apps - Only visible to your organization - Perfect for internal tools - No review required for use - Instant deployment ### Public Apps - Listed in the Teachfloor Marketplace - Available to all organizations - Requires review and approval - Potential for monetization ## Technology Stack ### Required - **React 18+**: UI framework - **JavaScript/TypeScript**: Programming languages - **Webpack**: Module bundler (configured by CLI) ### Provided - **Extension Kit**: Pre-built components library - **Teachfloor SDK**: Platform integration API - **CLI Tools**: Development and deployment utilities ### Optional - Any React-compatible libraries - State management (Redux, Zustand, etc.) - Styling solutions (Emotion, Tailwind, etc.) - Additional build tools ## Security & Privacy ### Sandboxing - Apps run in isolated sandboxes - Cannot access parent page directly - All communication through SDK ### Permissions - Explicit permission declarations in manifest - Granular access control - Transparent to users during installation ### Data Storage - Scoped to app and organization - Encrypted at rest - GDPR compliant ### Review Process - Code quality checks - Security vulnerability scanning - Privacy policy requirements - Terms of service compliance ## Limitations & Constraints ### Technical - Maximum 6 apps per organization - 10 MB bundle size limit (recommended) - 1000 API calls per minute (rate limiting) - 10 MB data storage per user ### Platform - Apps cannot modify core platform UI - Limited to defined viewports - Cannot run code on Teachfloor's servers (your own backend runs on your infrastructure — see [OAuth](./oauth) and [Webhooks](./webhooks)) - No direct database access ## Next Steps Now that you understand the basics, let's build your first app! → Continue to [Quickstart Guide](./quickstart) --- ## Document: /docs/apps/quickstart URL: /docs/apps/quickstart # Quickstart Guide Build your first Teachfloor app in 10 minutes! This guide walks you through creating a simple "Hello World" app that displays in the course list page. ## Prerequisites - Node.js 18.0+ installed - npm or yarn package manager - A Teachfloor account ## Setup Steps ### 1. Install the CLI Open your terminal and install the Teachfloor CLI globally: ```bash npm install -g @teachfloor/teachfloor-cli ``` Verify the installation: ```bash teachfloor version ``` ### 2. Authenticate Log in to your Teachfloor account: ```bash teachfloor login ``` You'll be prompted for: - **Email**: Your Teachfloor account email - **Password**: Your account password - **Organization**: Select your organization (if you have multiple) Once authenticated, verify your session: ```bash teachfloor whoami ``` ### 3. Create Your First App Create a new app called "hello-world": ```bash teachfloor apps create hello-world ``` You'll be prompted for: - **App ID**: Press Enter to accept the default (auto-generated) - **Display Name**: Enter "Hello World" - **Description**: Enter "My first Teachfloor app" - **Version**: Press Enter to accept "1.0.0" The CLI will: 1. Create the app on the platform 2. Generate the project structure 3. Install dependencies (React, Extension Kit, etc.) ``` ✓ Creating app... ✓ Setting up app structure... ✓ Installing npm dependencies... ✓ App "Hello World" created successfully in "hello-world". ``` ### 4. Explore the Project Structure Navigate into your app directory: ```bash cd hello-world ``` Your project structure looks like this: ``` hello-world/ ├── src/ │ ├── index.js # Entry point │ └── views/ │ └── App.jsx # Main view component ├── public/ │ └── index.html # HTML template with SDK ├── teachfloor-app.json # App manifest ├── package.json # Dependencies ├── webpack.config.js # Webpack config ├── tsconfig.json # TypeScript config └── .gitignore ``` ### 5. Add a View Add a view to display your app in the course list page: ```bash teachfloor apps add view ``` Select: - **Viewport**: `teachfloor.dashboard.course.list` - **Component Name**: Press Enter to accept "CourseListView" - **Generate example**: Yes This creates `src/views/CourseListView.jsx` and updates your manifest. ### 6. Customize Your Component Open `src/views/CourseListView.jsx` and modify it: ```jsx import React from 'react' import { Container, Text, Button, SimpleGrid, showToast, useExtensionContext, } from '@teachfloor/extension-kit' const CourseListView = () => { const { userContext } = useExtensionContext() const handleClick = () => { showToast('Hello from your app!', { color: 'green' }) } return ( Hello, {userContext.full_name}! Welcome to your first Teachfloor app. ) } export default CourseListView ``` ### 7. Start the Development Server Run the development server: ```bash teachfloor apps start ``` This will: 1. Validate your manifest 2. Upload the manifest to the platform 3. Open your browser to install the app 4. Start the webpack dev server on `http://localhost:3000` ``` ✓ Manifest file updated Install URL: https://app.teachfloor.com/your-org/courses?app=abc123@1.0.0 Starting development server... ``` ### 8. Test Your App 1. Your browser will open to the install URL 2. Click "Install" to add the app to your organization 3. Navigate to the course list page 4. You should see your app displayed! The app will hot-reload as you make changes to the code. ### 9. Build for Production When you're ready to deploy: 1. Stop the dev server (Ctrl+C) 2. Build the production bundle: ```bash teachfloor apps upload ``` This will: 1. Run `npm run build` 2. Bundle your app for production 3. Upload files to the platform 4. Create a new app version ``` ✓ Building the production bundle... ✓ Uploading files... ✓ App uploaded successfully. ``` ### 10. Publish to Marketplace (Optional) If you want to make your app available in the public marketplace: **Set Distribution to Public** First, set your app's distribution type to public: ```bash teachfloor apps set distribution ``` Select `public` when prompted. This updates your manifest: ```json { "distribution_type": "public" } ``` **Upload and Submit** 1. Upload your app with the updated manifest: ```bash teachfloor apps upload ``` 2. Go to your Teachfloor dashboard 3. Navigate to Settings → Apps 4. Find your app and click "Submit for Review" 5. Wait for approval from the Teachfloor team :::caution Only apps with `distribution_type: "public"` can be submitted for marketplace review. Private apps (`distribution_type: "private"`) are only visible to your organization and don't require review. ::: ## What's Next? Congratulations! You've built your first Teachfloor app. Here's what to explore next: ### Learn Core Concepts - [App Manifest](./core-concepts/app-manifest) - Configure your app - [Viewports](./core-concepts/viewports) - Understand placement options - [Extension Kit](./core-concepts/extension-kit/components) - Explore available components ### Add More Functionality - [Data Storage](./advanced-topics/data-storage) - Persist user data - [Permissions](./advanced-topics/permissions) - Access platform resources - [Extension Kit Integration](./core-concepts/extension-kit/integration) - Use platform features ### See Examples - [Example Apps](./references/examples) - Sample code and patterns --- **Ready to dive deeper?** Continue to [App Manifest](./core-concepts/app-manifest) --- ## Document: /docs/apps/core-concepts/app-manifest URL: /docs/apps/core-concepts/app-manifest # App Manifest The app manifest (`teachfloor-app.json`) defines your app's metadata, capabilities, permissions, and behavior. ## Overview The manifest is a JSON file at the root of your project: - Defines app name, description, and version - Specifies where your app displays (viewports) - Declares required permissions - Sets distribution type (public/private) - Configures post-installation actions ## Basic Structure Here's a minimal manifest: ```json { "id": "abc123def456", "version": "1.0.0", "name": "My App", "description": "A simple Teachfloor app", "distribution_type": "private" } ``` ## Complete Manifest Example ```json { "id": "abc123def456", "version": "1.2.0", "name": "Course Notes", "description": "Take notes while browsing courses and modules", "distribution_type": "public", "ui_extension": { "views": [ { "viewport": "teachfloor.dashboard.course.detail", "component": "CourseNotesView" }, { "viewport": "teachfloor.dashboard.course.module.detail", "component": "ModuleNotesView" } ], "permissions_policy": { "microphone": ["http://localhost:3000"], "purpose": "Enable speech-to-text for note taking" } }, "permissions": [ { "permission": "user:read", "purpose": "Display your name and profile" }, { "permission": "courses:read", "purpose": "Display course information in notes" } ], "post_install_action": { "type": "settings", "url": "https://example.com/setup" } } ``` ## Field Reference ### Required Fields #### `id` (string) Unique identifier for your app. Auto-generated during app creation. ```json "id": "abc123def456" ``` **Rules:** - Must be unique across all Teachfloor apps - Cannot be changed after creation - Automatically generated by CLI #### `version` (string) Semantic version of your app following [semver](https://semver.org/) format. ```json "version": "1.2.3" ``` **Rules:** - Must follow `MAJOR.MINOR.PATCH` format - Examples: `1.0.0`, `2.1.5`, `0.5.0-beta` - Increment when uploading new versions **Versioning Guidelines:** - **MAJOR**: Breaking changes - **MINOR**: New features, backward compatible - **PATCH**: Bug fixes, backward compatible #### `name` (string) Display name shown to users in the marketplace and dashboard. ```json "name": "Course Notes" ``` **Rules:** - Maximum 50 characters - Should be descriptive and unique - Used in app listings and UI #### `description` (string) Short description of what your app does. ```json "description": "Take notes while browsing courses and modules" ``` **Rules:** - Maximum 200 characters - Should clearly explain the app's purpose - Displayed in marketplace listings ### Distribution #### `distribution_type` (string) Determines how your app is distributed. ```json "distribution_type": "public" ``` **Values:** - `"private"`: Only your organization can install (default) - `"public"`: Listed in marketplace for all organizations :::info See [Deployment Guide](./advanced-topics/deployment#distribution-types) for detailed information on private vs public distribution. ::: ### UI Extension #### `ui_extension` (object, optional) Defines where and how your app displays in the platform. :::info The `ui_extension` field is optional. Apps without it can function as backend integrations listening to platform events. ::: ##### `views` (array) List of views your app provides. ```json "ui_extension": { "views": [ { "viewport": "teachfloor.dashboard.course.list", "component": "CourseListView" }, { "viewport": "teachfloor.dashboard.course.detail", "component": "CourseDetailView" } ] } ``` **View Object:** - `viewport` (string): Where the view displays (must be an exact match to an available viewport) - `component` (string): React component name (must match filename without extension) :::caution Viewports require exact string matches. Wildcard patterns are not supported. See [Viewports System](./viewports) for available viewports. ::: ##### `permissions_policy` (object) Browser permissions your app needs (microphone, camera, etc.). ```json "ui_extension": { "permissions_policy": { "microphone": ["http://localhost:3000", "https://app.teachfloor.com"], "camera": ["http://localhost:3000"], "purpose": "Enable video recording for assignments" } } ``` **Available Permissions:** - `microphone`: Audio input - `camera`: Video input - `geolocation`: Location access - `clipboard-write`: Clipboard access **Fields:** - Permission name: Array of allowed origins - `purpose`: User-facing explanation (required) ### Permissions #### `permissions` (array) Platform permissions your app needs to access Teachfloor resources. ```json "permissions": [ { "permission": "courses:read", "purpose": "Display course information in widgets" }, { "permission": "user_events:read", "purpose": "Track learning progress" } ] ``` **Permission Object:** - `permission` (string): Permission identifier - `purpose` (string): User-facing explanation of why you need it **Important**: - Only request permissions you actually use - Provide clear, user-facing explanations - Users see permission requests during installation - Write permissions (`*:write`) automatically include read access :::info See [Permissions Reference](./advanced-topics/permissions) for the complete list of available permissions, their descriptions, and permission hierarchy. ::: ### Post-Install Action #### `post_install_action` (object) Defines what happens after a user installs your app. ```json "post_install_action": { "type": "settings" } ``` **Type: Settings** Redirect to app settings page: ```json { "type": "settings" } ``` **Type: External** Redirect to external URL: ```json { "type": "external", "url": "https://example.com/setup?user=123" } ``` **Use Cases:** - Configuration wizard - Account connection - Welcome tutorial - Feature introduction ## Manifest Validation The CLI automatically validates your manifest before upload. ### Validation Rules #### Required Fields - `id`, `version`, `name` must be present #### Version Format - Must match semver pattern: `^\d+\.\d+\.\d+(-[\w.]+)?$` - Valid: `1.0.0`, `2.1.5`, `1.0.0-beta.1` - Invalid: `1.0`, `v1.0.0`, `1.0.0.0` #### Component Names - Must be valid React component names - PascalCase only - Valid: `MyView`, `CourseDetailView` - Invalid: `myView`, `my-view`, `my_view` #### Viewport Names - Must match known viewport patterns - See [Viewports documentation](./viewports) ### Manual Validation The manifest is automatically validated when you run: ```bash teachfloor apps start # or teachfloor apps upload ``` ## Managing Manifests ### Updating Metadata #### Via CLI Commands Update distribution type: ```bash teachfloor apps set distribution ``` Add permission: ```bash teachfloor apps grant permission ``` Remove permission: ```bash teachfloor apps revoke permission ``` Add view: ```bash teachfloor apps add view ``` Remove view: ```bash teachfloor apps remove view ``` #### Manual Editing 1. Open `teachfloor-app.json` in your editor 2. Make changes 3. Save the file 4. Run `teachfloor apps start` or `teachfloor apps upload` The CLI will validate and upload the updated manifest. ### Version Management Once a version is published, it becomes locked and cannot be modified. To release updates, increment the version number and upload again. :::info See [Deployment Guide](./advanced-topics/deployment#version-management) for complete information on version states, semantic versioning, and deployment process. ::: ### Multi-Environment Manifests Use different manifests for development and production: **Development** (`teachfloor-app.dev.json`): ```json { "id": "abc123", "version": "1.0.0-dev", "name": "My App (Dev)", "distribution_type": "private", "ui_extension": { "permissions_policy": { "microphone": ["http://localhost:3000"] } } } ``` **Production** (`teachfloor-app.json`): ```json { "id": "abc123", "version": "1.0.0", "name": "My App", "distribution_type": "public", "ui_extension": { "permissions_policy": { "microphone": ["https://app.teachfloor.com"] } } } ``` Start with custom manifest: ```bash teachfloor apps start --manifest teachfloor-app.dev.json ``` ## Next Steps → Continue to [Viewports System](./viewports) ## Additional Resources - [Best Practices](./references/best-practices) - Naming, descriptions, permissions, and versioning guidelines - [Troubleshooting Guide](./references/troubleshooting) - Common manifest errors and solutions - [Examples](./references/examples) - Complete manifest examples - [Permissions Reference](./advanced-topics/permissions) - [CLI Commands](./references/cli) --- ## Document: /docs/apps/core-concepts/viewports URL: /docs/apps/core-concepts/viewports # Viewports System Viewports define where your app displays within the Teachfloor platform. Viewport is one of two axes that fully describe where and how your app renders. The other axis — [surface](./surfaces) — answers *how* your app is presented (as a drawer that opens from the app dock, or as a widget embedded inline). Together, `(viewport, surface)` uniquely specifies each entry in your manifest. ## What is a Viewport? A viewport is a specific location in the Teachfloor dashboard where your app renders its UI. Each viewport corresponds to a page or section of the platform. ### Viewport Structure Viewports follow a hierarchical naming pattern: ``` teachfloor.{surface}.{resource}.{view-type} ``` **Example**: `teachfloor.dashboard.course.detail` - `teachfloor`: Platform namespace - `dashboard`: Surface where the view renders - `course`: Resource being viewed - `detail`: View type ## Available Viewports ### Quick Reference Table | Viewport | Page | Path Pattern | Common Use Cases | |----------|------|--------------|------------------| | **Course Management** | | `teachfloor.dashboard.course.list` | Course listing | `/:org/courses` | Course directory widgets, filters, quick actions | | `teachfloor.dashboard.course.detail` | Course detail | `/:org/courses/:id` | Course analytics, notes, supplementary materials | | `teachfloor.dashboard.course.module.list` | Module list | `/:org/courses/:id/modules` | Module overview, navigation tools | | `teachfloor.dashboard.course.module.detail` | Module detail | `/:org/courses/:id/modules/:id` | Module tools, notes, progress tracking | | `teachfloor.dashboard.course.element.detail` | Element detail | `/:org/courses/:id/modules/:id/elements/:id` | Element annotations, supplementary content | | `teachfloor.dashboard.course.assessment.list` | Assessment list | `/:org/courses/:id/assessments` | Assessment overview, quiz management | | `teachfloor.dashboard.course.progress.detail` | Course progress | `/:org/courses/:id/progress` | Progress tracking, completion status | | `teachfloor.dashboard.course.calendar.detail` | Course calendar | `/:org/courses/:id/calendar` | Schedule view, deadline tracking | | `teachfloor.dashboard.course.member.list` | Course members | `/:org/courses/:id/directory` | Student list, member management | | **Community** | | `teachfloor.dashboard.community.overview` | Community home (cross-channel feed) | `/:org/community` | Cross-channel feed widgets, suggested content, digest tools | | `teachfloor.dashboard.community.channel.detail` | Single channel page | `/:org/community/:channelId` | Social features, engagement tools, moderation | | `teachfloor.dashboard.community.post.detail` | Community post detail | `/:org/community/:channelId/posts/:postId` | Post sidebars, reaction tools, translation | | `teachfloor.dashboard.community.member.list` | Community members | `/:org/community/:channelId/members` | Member profiles, networking tools, search | | `teachfloor.dashboard.community.event.list` | Community events | `/:org/community/events` | Calendar exports, RSVP tooling, scheduling helpers | | `teachfloor.dashboard.community.event.detail` | Community event detail | `/:org/community/events/:eventId` | Attendee tools, meeting integrations, reminders | | **Settings** | | `teachfloor.dashboard.settings.general.detail` | General settings | `/:org/settings/general` | Organization-wide integrations, preferences | | `teachfloor.dashboard.settings.customization.domain.detail` | Customization · Domain | `/:org/settings/customization/domain` | Domain configuration widgets, DNS helpers | | `teachfloor.dashboard.settings.customization.appearance.detail` | Customization · Appearance | `/:org/settings/customization/appearance` | Theme tools, brand previews | | `teachfloor.dashboard.settings.customization.smtp.detail` | Customization · SMTP | `/:org/settings/customization/smtp` | Email-delivery diagnostics | | `teachfloor.dashboard.settings.customization.checkout.detail` | Customization · Checkout | `/:org/settings/customization/checkout` | Checkout experiments, payment tweaks | | `teachfloor.dashboard.settings.customization.login.detail` | Customization · Login | `/:org/settings/customization/login` | Login-screen branding | | `teachfloor.dashboard.settings.customization.labels.detail` | Customization · Labels | `/:org/settings/customization/labels` | Custom terminology tools | | `teachfloor.dashboard.settings.customization.achievements.detail` | Customization · Achievements | `/:org/settings/customization/achievements` | Gamification configuration | | `teachfloor.dashboard.settings.customization.profile-layout.detail` | Customization · Profile layout | `/:org/settings/customization/profile-layout` | Profile field arrangement tools | | `teachfloor.dashboard.settings.customization.dashboards.detail` | Customization · Dashboards | `/:org/settings/customization/dashboards` | Home-dashboard widget catalog, layout authoring tools | | `teachfloor.dashboard.settings.team.list` | Team management | `/:org/settings/team` | Team collaboration tools, role management | | `teachfloor.dashboard.settings.billing.detail` | Billing | `/:org/settings/billing` | Usage analytics, cost tracking | | `teachfloor.dashboard.settings.integration.list` | Integrations | `/:org/settings/integrations` | Third-party integrations, API tools | | `teachfloor.dashboard.settings.notification.list` | Notifications | `/:org/settings/notifications` | Custom notification rules, digest tools | | `teachfloor.dashboard.settings.custom-field.list` | Custom fields | `/:org/settings/custom-fields` | Custom field management, data import tools | | `teachfloor.dashboard.settings.branch.list` | Branches | `/:org/settings/branches` | Branch management, multi-tenant tools | | `teachfloor.dashboard.settings.sanction.list` | Sanctions | `/:org/settings/sanctions` | Restriction policies, moderation tooling | | `teachfloor.dashboard.settings.import.list` | Import data | `/:org/settings/import` | Bulk import tools, data migration | | `teachfloor.dashboard.settings.app.list` | Apps | `/:org/settings/apps` | Installed apps, app marketplace | | **User Management** | | `teachfloor.dashboard.account.detail` | User account | `/:org/account` | Personal tools, user preferences, integrations | | `teachfloor.dashboard.profile.detail` | User profile | `/:org/users/:userId` | Profile widgets, member insights | | `teachfloor.dashboard.learner.list` | Learners | `/:org/learners` | Learner analytics, bulk actions, import tools | | **Commerce** | | `teachfloor.dashboard.payment.list` | Payments | `/:org/payments` | Payment analytics, invoicing tools | | **Messaging** | | `teachfloor.dashboard.messaging.thread.detail` | Thread | `/:org/messaging/threads/:thread` | Thread sidebars, translation tools, message-level integrations | | **Workspace** | | `teachfloor.dashboard.dashboard.detail` | Home dashboard | `/:org/dashboard` | Widget-based home insights, custom KPIs, welcome banners | | `teachfloor.dashboard.analytics.detail` | Analytics | `/:org/analytics` | Custom dashboards, exports, alerts | | `teachfloor.dashboard.library.detail` | Library drive | `/:org/library/:drive` | Asset browsers, content pickers | | `teachfloor.dashboard.automation.list` | Automations | `/:org/automations` | Workflow inspectors, audit tools | | `teachfloor.dashboard.getstarted.detail` | Get started | `/:org/getstarted` | Onboarding hints, checklists | | **App Settings** | | `settings` | App settings | `/:org/settings/apps/:appId` | App configuration, user preferences | ### Course Management #### `teachfloor.dashboard.course.list` **Displays on**: Course listing page **Path**: `/:organization/courses` **Use cases**: Course directory widgets, filters, quick actions ```json { "viewport": "teachfloor.dashboard.course.list", "component": "CourseListView" } ``` #### `teachfloor.dashboard.course.detail` **Displays on**: Individual course page **Path**: `/:organization/courses/:courseId` **Use cases**: Course analytics, notes, supplementary materials ```json { "viewport": "teachfloor.dashboard.course.detail", "component": "CourseDetailView" } ``` #### `teachfloor.dashboard.course.module.detail` **Displays on**: Module detail page **Path**: `/:organization/courses/:courseId/modules/:moduleId` **Use cases**: Module-specific tools, notes, progress tracking ```json { "viewport": "teachfloor.dashboard.course.module.detail", "component": "ModuleDetailView" } ``` #### `teachfloor.dashboard.course.element.detail` **Displays on**: Learning element page (assignments, videos, etc.) **Path**: `/:organization/courses/:courseId/modules/:moduleId/elements/:elementId` **Use cases**: Element annotations, supplementary content, tools ```json { "viewport": "teachfloor.dashboard.course.element.detail", "component": "ElementDetailView" } ``` #### `teachfloor.dashboard.course.module.list` **Displays on**: Module list page **Path**: `/:organization/courses/:courseId/modules` **Use cases**: Module overview, navigation tools ```json { "viewport": "teachfloor.dashboard.course.module.list", "component": "ModuleListView" } ``` #### `teachfloor.dashboard.course.assessment.list` **Displays on**: Assessment list page **Path**: `/:organization/courses/:courseId/assessments` **Use cases**: Assessment overview, quiz management ```json { "viewport": "teachfloor.dashboard.course.assessment.list", "component": "AssessmentListView" } ``` #### `teachfloor.dashboard.course.progress.detail` **Displays on**: Course progress page **Path**: `/:organization/courses/:courseId/progress` **Use cases**: Progress tracking, completion status ```json { "viewport": "teachfloor.dashboard.course.progress.detail", "component": "CourseProgressView" } ``` #### `teachfloor.dashboard.course.calendar.detail` **Displays on**: Course calendar page **Path**: `/:organization/courses/:courseId/calendar` **Use cases**: Schedule view, deadline tracking ```json { "viewport": "teachfloor.dashboard.course.calendar.detail", "component": "CourseCalendarView" } ``` #### `teachfloor.dashboard.course.member.list` **Displays on**: Course members page **Path**: `/:organization/courses/:courseId/directory` **Use cases**: Learner list, member management ```json { "viewport": "teachfloor.dashboard.course.member.list", "component": "CourseMemberListView" } ``` ### Community #### `teachfloor.dashboard.community.overview` **Displays on**: Community home (cross-channel feed) — the `/community` landing page **Path**: `/:organization/community` **Use cases**: Cross-channel feed widgets, suggested content, digest tools The workspace-level home that aggregates posts across every channel the viewer can see. Stripe-style `overview` rather than `feed`/`list` because no single resource is being listed — distinct from `community.channel.detail`, which targets a single channel. ```json { "viewport": "teachfloor.dashboard.community.overview", "component": "CommunityOverviewView" } ``` #### `teachfloor.dashboard.community.channel.detail` **Displays on**: Single channel page **Path**: `/:organization/community/:channelId` **Use cases**: Social features, engagement tools, moderation The primary resource on this page is the Channel itself — posts are its content — so the viewport follows Stripe's `{resource}.detail` convention. ```json { "viewport": "teachfloor.dashboard.community.channel.detail", "component": "CommunityChannelView" } ``` #### `teachfloor.dashboard.community.post.detail` **Displays on**: Individual community post page **Path**: `/:organization/community/:channelId/posts/:postId` **Use cases**: Post sidebars, reaction tools, translation, attached references ```json { "viewport": "teachfloor.dashboard.community.post.detail", "component": "CommunityPostView" } ``` #### `teachfloor.dashboard.community.member.list` **Displays on**: Community members directory **Path**: `/:organization/community/:channelId/members` **Use cases**: Member profiles, networking tools, search ```json { "viewport": "teachfloor.dashboard.community.member.list", "component": "CommunityMembersView" } ``` #### `teachfloor.dashboard.community.event.list` **Displays on**: Community events list **Path**: `/:organization/community/events` **Use cases**: Calendar exports, RSVP tooling, scheduling helpers ```json { "viewport": "teachfloor.dashboard.community.event.list", "component": "CommunityEventsView" } ``` #### `teachfloor.dashboard.community.event.detail` **Displays on**: Single community event page **Path**: `/:organization/community/events/:eventId` **Use cases**: Attendee tools, meeting integrations, reminders, follow-up content ```json { "viewport": "teachfloor.dashboard.community.event.detail", "component": "CommunityEventView" } ``` ### Settings #### `teachfloor.dashboard.settings.general.detail` **Displays on**: General settings page **Path**: `/:organization/settings/general` **Use cases**: Organization-wide integrations, preferences ```json { "viewport": "teachfloor.dashboard.settings.general.detail", "component": "GeneralSettingsView" } ``` #### `teachfloor.dashboard.settings.customization.domain.detail` **Displays on**: Customization · Domain subtab **Path**: `/:organization/settings/customization/domain` **Use cases**: Domain configuration widgets, DNS helpers ```json { "viewport": "teachfloor.dashboard.settings.customization.domain.detail", "component": "CustomizationDomainView" } ``` #### `teachfloor.dashboard.settings.customization.appearance.detail` **Displays on**: Customization · Appearance subtab **Path**: `/:organization/settings/customization/appearance` **Use cases**: Theme tools, brand previews ```json { "viewport": "teachfloor.dashboard.settings.customization.appearance.detail", "component": "CustomizationAppearanceView" } ``` #### `teachfloor.dashboard.settings.customization.smtp.detail` **Displays on**: Customization · SMTP subtab **Path**: `/:organization/settings/customization/smtp` **Use cases**: Email-delivery diagnostics ```json { "viewport": "teachfloor.dashboard.settings.customization.smtp.detail", "component": "CustomizationSmtpView" } ``` #### `teachfloor.dashboard.settings.customization.checkout.detail` **Displays on**: Customization · Checkout subtab **Path**: `/:organization/settings/customization/checkout` **Use cases**: Checkout experiments, payment tweaks ```json { "viewport": "teachfloor.dashboard.settings.customization.checkout.detail", "component": "CustomizationCheckoutView" } ``` #### `teachfloor.dashboard.settings.customization.login.detail` **Displays on**: Customization · Login subtab **Path**: `/:organization/settings/customization/login` **Use cases**: Login-screen branding ```json { "viewport": "teachfloor.dashboard.settings.customization.login.detail", "component": "CustomizationLoginView" } ``` #### `teachfloor.dashboard.settings.customization.labels.detail` **Displays on**: Customization · Labels subtab **Path**: `/:organization/settings/customization/labels` **Use cases**: Custom terminology tools ```json { "viewport": "teachfloor.dashboard.settings.customization.labels.detail", "component": "CustomizationLabelsView" } ``` #### `teachfloor.dashboard.settings.customization.achievements.detail` **Displays on**: Customization · Achievements subtab (visible only when the workspace has the achievements feature enabled) **Path**: `/:organization/settings/customization/achievements` **Use cases**: Gamification configuration ```json { "viewport": "teachfloor.dashboard.settings.customization.achievements.detail", "component": "CustomizationAchievementsView" } ``` #### `teachfloor.dashboard.settings.customization.profile-layout.detail` **Displays on**: Customization · Profile layout subtab (visible only to owners and admins) **Path**: `/:organization/settings/customization/profile-layout` **Use cases**: Profile field arrangement tools ```json { "viewport": "teachfloor.dashboard.settings.customization.profile-layout.detail", "component": "CustomizationProfileLayoutView" } ``` #### `teachfloor.dashboard.settings.customization.dashboards.detail` **Displays on**: Customization · Dashboards subtab — the admin page for managing home-dashboard layouts and widgets **Path**: `/:organization/settings/customization/dashboards` **Use cases**: Widget catalogs, layout authoring tools, dashboard templates ```json { "viewport": "teachfloor.dashboard.settings.customization.dashboards.detail", "component": "CustomizationDashboardsView" } ``` #### `teachfloor.dashboard.settings.team.list` **Displays on**: Team management page **Path**: `/:organization/settings/team` **Use cases**: Team collaboration tools, role management ```json { "viewport": "teachfloor.dashboard.settings.team.list", "component": "TeamSettingsView" } ``` #### `teachfloor.dashboard.settings.billing.detail` **Displays on**: Billing settings page **Path**: `/:organization/settings/billing` **Use cases**: Usage analytics, cost tracking ```json { "viewport": "teachfloor.dashboard.settings.billing.detail", "component": "BillingView" } ``` #### `teachfloor.dashboard.settings.integration.list` **Displays on**: Integrations page **Path**: `/:organization/settings/integrations` **Use cases**: Third-party integrations, API tools ```json { "viewport": "teachfloor.dashboard.settings.integration.list", "component": "IntegrationView" } ``` #### `teachfloor.dashboard.settings.notification.list` **Displays on**: Notification settings page **Path**: `/:organization/settings/notifications` **Use cases**: Custom notification rules, digest tools ```json { "viewport": "teachfloor.dashboard.settings.notification.list", "component": "NotificationView" } ``` #### `teachfloor.dashboard.settings.custom-field.list` **Displays on**: Custom fields settings page **Path**: `/:organization/settings/custom-fields` **Use cases**: Custom field management, data import tools ```json { "viewport": "teachfloor.dashboard.settings.custom-field.list", "component": "CustomFieldView" } ``` #### `teachfloor.dashboard.settings.branch.list` **Displays on**: Branches settings page **Path**: `/:organization/settings/branches` **Use cases**: Branch management, multi-tenant tools ```json { "viewport": "teachfloor.dashboard.settings.branch.list", "component": "BranchListView" } ``` #### `teachfloor.dashboard.settings.sanction.list` **Displays on**: Sanctions settings page (visible only when the workspace has the sanctions feature enabled) **Path**: `/:organization/settings/sanctions` **Use cases**: Restriction policies, moderation tooling ```json { "viewport": "teachfloor.dashboard.settings.sanction.list", "component": "SanctionListView" } ``` #### `teachfloor.dashboard.settings.import.list` **Displays on**: Import data page **Path**: `/:organization/settings/import` **Use cases**: Bulk import tools, data migration ```json { "viewport": "teachfloor.dashboard.settings.import.list", "component": "ImportView" } ``` #### `teachfloor.dashboard.settings.app.list` **Displays on**: Apps settings page **Path**: `/:organization/settings/apps` **Use cases**: Installed apps, app marketplace ```json { "viewport": "teachfloor.dashboard.settings.app.list", "component": "AppListView" } ``` ### User Management #### `teachfloor.dashboard.account.detail` **Displays on**: User account settings page **Path**: `/:organization/account` **Use cases**: Personal tools, user preferences, integrations ```json { "viewport": "teachfloor.dashboard.account.detail", "component": "AccountView" } ``` #### `teachfloor.dashboard.profile.detail` **Displays on**: User profile page **Path**: `/:organization/users/:userId` **Use cases**: Profile widgets, member insights, supplementary user info ```json { "viewport": "teachfloor.dashboard.profile.detail", "component": "ProfileDetailView" } ``` #### `teachfloor.dashboard.learner.list` **Displays on**: Learners management page **Path**: `/:organization/learners` **Use cases**: Learner analytics, bulk actions, import tools ```json { "viewport": "teachfloor.dashboard.learner.list", "component": "LearnerListView" } ``` ### Commerce #### `teachfloor.dashboard.payment.list` **Displays on**: Payments page **Path**: `/:organization/payments` **Use cases**: Payment analytics, invoicing tools ```json { "viewport": "teachfloor.dashboard.payment.list", "component": "PaymentView" } ``` ### Messaging #### `teachfloor.dashboard.messaging.thread.detail` **Displays on**: Messaging thread page **Path**: `/:organization/messaging/threads/:threadId` **Use cases**: Thread sidebars, translation tools, message-level integrations ```json { "viewport": "teachfloor.dashboard.messaging.thread.detail", "component": "MessagingThreadView" } ``` ### Workspace #### `teachfloor.dashboard.dashboard.detail` **Displays on**: Home dashboard page — the user's landing screen with widget-based insights **Path**: `/:organization/dashboard` **Use cases**: KPI widgets, welcome banners, announcements, custom org-level insights ```json { "viewport": "teachfloor.dashboard.dashboard.detail", "component": "DashboardView" } ``` #### `teachfloor.dashboard.analytics.detail` **Displays on**: Analytics page **Path**: `/:organization/analytics` **Use cases**: Custom dashboards, exports, alerts ```json { "viewport": "teachfloor.dashboard.analytics.detail", "component": "AnalyticsView" } ``` #### `teachfloor.dashboard.library.detail` **Displays on**: Library drive page **Path**: `/:organization/library/:drive` **Use cases**: Asset browsers, content pickers ```json { "viewport": "teachfloor.dashboard.library.detail", "component": "LibraryDriveView" } ``` #### `teachfloor.dashboard.automation.list` **Displays on**: Automations page **Path**: `/:organization/automations` **Use cases**: Workflow inspectors, audit tools ```json { "viewport": "teachfloor.dashboard.automation.list", "component": "AutomationListView" } ``` #### `teachfloor.dashboard.getstarted.detail` **Displays on**: Get started page **Path**: `/:organization/getstarted` **Use cases**: Onboarding hints, checklists ```json { "viewport": "teachfloor.dashboard.getstarted.detail", "component": "GetStartedView" } ``` ### App Settings #### `settings` **Displays on**: Your app's settings page **Path**: `/:organization/settings/apps/:appId` **Use cases**: App configuration, user preferences ```json { "viewport": "settings", "component": "AppSettingsView" } ``` :::info The `settings` viewport provides a dedicated settings page for your app. ::: ## Viewport Context When your app renders in a viewport, it receives context about the current page: ```javascript import { useExtensionContext } from '@teachfloor/extension-kit' const MyView = () => { const { environment } = useExtensionContext() console.log(environment.viewport) // "teachfloor.dashboard.course.detail" console.log(environment.path) // "/myorg/courses/123" return
Current viewport: {environment.viewport}
} ``` ### Available Context ```typescript environment: { initialized: boolean // SDK ready state viewport: string // Current viewport ID path: string // Current URL path } ``` ## Viewport Matching ### How Matching Works 1. User navigates to a page (e.g., `/myorg/courses`) 2. Platform determines viewport (`teachfloor.dashboard.course.list`) 3. Platform finds apps with views matching the exact viewport 4. Matching app views are rendered in their designated positions :::caution Viewports require exact string matches. Wildcard patterns are not supported. ::: ### Example Scenario Your app manifest: ```json { "ui_extension": { "views": [ { "viewport": "teachfloor.dashboard.course.detail", "component": "CourseDetailView" }, { "viewport": "teachfloor.dashboard.course.list", "component": "CourseListView" }, { "viewport": "settings", "component": "SettingsView" } ] } } ``` **User visits course detail page (`/org/courses/123`)**: - ✅ `CourseDetailView` renders (viewport: `teachfloor.dashboard.course.detail`) - ❌ `CourseListView` does not render (different viewport) **User visits course list page (`/org/courses`)**: - ✅ `CourseListView` renders (viewport: `teachfloor.dashboard.course.list`) - ❌ `CourseDetailView` does not render (different viewport) **User visits app settings page (`/org/settings/apps/yourapp`)**: - ✅ `SettingsView` renders (viewport: `settings`) ## View Component Structure ### Basic View Component ```jsx import React from 'react' import { Container, Text, useExtensionContext } from '@teachfloor/extension-kit' const CourseListView = () => { const { environment, userContext } = useExtensionContext() return ( Hello {userContext.full_name} You're viewing: {environment.viewport} ) } export default CourseListView ``` ### Viewport-Aware Component ```jsx import React from 'react' import { useExtensionContext } from '@teachfloor/extension-kit' const SmartView = () => { const { environment } = useExtensionContext() // Render different UI based on viewport if (environment.viewport.includes('course.detail')) { return } if (environment.viewport.includes('settings')) { return } return } ``` ### Dynamic View Loader ```jsx import React from 'react' import { ExtensionViewLoader } from '@teachfloor/extension-kit' import manifest from '../../teachfloor-app.json' const App = () => { return ( import(`./${componentName}`)} /> ) } export default App ``` ## Adding Views to Your App ### Using CLI ```bash teachfloor apps add view ``` 1. Select viewport from list 2. Enter component name (PascalCase) 3. Choose whether to generate example code ### Manual Addition 1. Create component file: ```bash touch src/views/CourseListView.jsx ``` 2. Update manifest: ```json { "ui_extension": { "views": [ { "viewport": "teachfloor.dashboard.course.list", "component": "CourseListView" } ] } } ``` 3. Implement component: ```jsx import React from 'react' import { Container, Text } from '@teachfloor/extension-kit' const CourseListView = () => { return ( My Course List Widget ) } export default CourseListView ``` ## Removing Views ### Using CLI ```bash teachfloor apps remove view ``` ### Manual Removal 1. Delete component file 2. Remove from manifest: ```json { "ui_extension": { "views": [ // Remove the view object ] } } ``` ## Next Steps → Continue to [Extension Kit Components](./extension-kit/components) ## Additional Resources - [Best Practices](/docs/apps/references/best-practices) - Viewport selection and performance optimization - [Troubleshooting Guide](/docs/apps/references/troubleshooting) - Viewport issues and debugging - [Examples](/docs/apps/references/examples) - Multi-viewport app examples - [Extension Kit Integration](./extension-kit/integration) --- ## Document: /docs/apps/core-concepts/surfaces URL: /docs/apps/core-concepts/surfaces # Surfaces Surfaces describe **how** your app renders inside Teachfloor — as a drawer that slides in from the app dock, or as a widget embedded inline in a layout. Combined with a [viewport](./viewports), the pair `(viewport, surface)` fully specifies where and how your app is mounted. ## Two Axes: Viewport and Surface Every entry in your manifest's `ui_extension.views` is defined by two orthogonal properties: | Axis | Answers | Example | |---|---|---| | **Viewport** | *Where* is the user? | `teachfloor.dashboard.course.detail` | | **Surface** | *How* is your app rendered? | `drawer` or `widget` | An app can register **multiple entries at the same viewport** as long as they use different surfaces (or, for widgets, different widget ids — see [Multiple Widgets](#multiple-widgets-at-the-same-viewport)). Kit picks the correct component using both fields. ## Available Surfaces ### Drawer A right-side panel opened from the app dock. This is the default surface — if a manifest entry omits `surface`, it renders as a drawer for back-compat with pre-surfaces apps. **Typical use:** on-demand focus interactions — open the app, look at something, close it. Cohort presence, quick notes, calculators, help articles. ```json { "surface": "drawer", "viewport": "teachfloor.dashboard.course.detail", "component": "CourseHelper" } ``` The `surface` field is optional here — omitting it produces the same result: ```json { "viewport": "teachfloor.dashboard.course.detail", "component": "CourseHelper" } ``` ### Widget A cell in a layout that hosts widget slots. Widgets are always visible on the page (no click-to-open) and sit alongside native platform widgets. **Typical use:** always-on displays — dashboards, progress panels, live counters, feature highlights. Widget entries carry an extra `widget` block with three required fields: ```json { "surface": "widget", "viewport": "teachfloor.dashboard.dashboard.detail", "component": "CourseProgressWidget", "widget": { "id": "course_progress", "name": "Course Progress", "description": "Aggregate progress across all enrolled courses." } } ``` - **`id`** — stable slug (`^[a-z][a-z0-9_]*$`), **unique per app** across all widget declarations. Used as the runtime identifier when your bundle contains multiple widget components. Part of the composite key stored in the dashboard row, so renaming your component doesn't invalidate placed layouts. - **`name`** — shown in the admin's widget picker and in the app install-consent surface list. ≤60 chars. - **`description`** — one-line explanation shown alongside the name in the picker. ≤200 chars. ## A Full Manifest Example An app registering a drawer plus two widgets: ```json { "id": "6a42a271ae2ee", "version": "1.0.0", "name": "Course Progress Panel", "description": "See your progress across all enrolled courses.", "distribution_type": "public", "ui_extension": { "views": [ { "surface": "drawer", "viewport": "teachfloor.dashboard.dashboard.detail", "component": "ProgressDetailView" }, { "surface": "widget", "viewport": "teachfloor.dashboard.dashboard.detail", "component": "CourseProgressWidget", "widget": { "id": "course_progress", "name": "Course Progress", "description": "Aggregate progress across all enrolled courses." } }, { "surface": "widget", "viewport": "teachfloor.dashboard.dashboard.detail", "component": "LearningStreakWidget", "widget": { "id": "learning_streak", "name": "Learning Streak", "description": "Current daily study streak with a 7-day heatmap." } } ] }, "permissions": [] } ``` The two widgets share the same viewport — Kit disambiguates by `widget.id` at render time. ## Reading the Surface at Runtime The current surface is exposed via `useExtensionContext()`, grouped inside `environment`: ```jsx import { useExtensionContext, SURFACES } from '@teachfloor/extension-kit' const MyView = () => { const { environment } = useExtensionContext() if (environment.surface === SURFACES.WIDGET) { // compact layout — widget slot is usually small } if (environment.surface === SURFACES.DRAWER) { // full drawer layout with headers and sections } } ``` Prefer the `SURFACES` constant over the bare `'drawer'` / `'widget'` strings — it's exported specifically to survive future renames. Apps that don't need surface-aware behavior can ignore `environment.surface` entirely — most components render the same regardless of surface. ## Widget Auto-Height with `` **Requires `@teachfloor/extension-kit` ≥ 1.27.0.** Earlier versions of the kit don't ship `` or the `SURFACES` constant. Bump your app's dependency before wrapping widgets in ``. Wrap your widget's root element in `` and the slot in the dashboard grid will automatically fit your content's height. No aspect ratio needed: ```jsx import { WidgetView, Text, Stack } from '@teachfloor/extension-kit' const LearningStreakWidget = () => ( 7-day streak Keep going — you're on fire. ) ``` `WidgetView` accepts the same layout props as `Container` (`p`, `px`, `py`, `sx`, etc.) — spacing shorthands work directly. Under the hood, `WidgetView` observes its own DOM height and emits it to the host over RPC. The host applies the reported height to the slot's container, so a widget with sparse content stays compact and a widget with a scrolling list grows to match. The same mechanism powers ``. **Admin override:** if the dashboard admin explicitly picks an aspect ratio when configuring the widget slot, that ratio wins over the emitted height. Auto-height is the default; forced ratios are the escape hatch. ## Multiple Widgets at the Same Viewport A single app bundle can register multiple widgets at the same viewport as long as each has a distinct `widget.id`. This lets one deploy provide, say, a *Course Progress* widget and a *Learning Streak* widget from the same codebase. Kit picks each widget's component using `environment.view.id`: ```jsx import { useExtensionContext, SURFACES } from '@teachfloor/extension-kit' import CourseProgressWidget from './widgets/CourseProgressWidget' import LearningStreakWidget from './widgets/LearningStreakWidget' const WIDGETS = { course_progress: CourseProgressWidget, learning_streak: LearningStreakWidget, } const App = () => { const { environment } = useExtensionContext() if (environment.surface === SURFACES.WIDGET) { const Component = WIDGETS[environment.view.id] return Component ? : null } return } ``` In most cases you can skip this dispatch entirely and let `ExtensionViewLoader` (from `@teachfloor/extension-kit`) resolve the right component by mapping `widget.id` to your components — see the [Extension Kit Components](./extension-kit/components) chapter. ### Runtime `environment.viewport` is always the actual route A widget declared as `viewport: '*'` that lands on the dashboard receives `environment.viewport === 'teachfloor.dashboard.dashboard.detail'` at runtime — never `'*'`. Wildcards are declaration scope; the runtime value is always concrete. This lets your widget code react to *where it landed* (fetch course-specific data on a course page, org-wide data on the main dashboard) without conflating declaration with location. ## CLI Helpers The Teachfloor CLI scaffolds drawer views and widgets with the correct manifest shape: ```bash # Add a new drawer view (prompts for viewport + component name) teachfloor apps add view # Add a new widget (prompts for viewport, widget id, name, description, component) teachfloor apps add widget # Remove a widget by id teachfloor apps remove widget ``` See the [CLI reference](./references/cli) for the full flag list. ## Continue to - [Extension Kit Components](./extension-kit/components) — the UI primitives you'll use inside your surfaces, including `` and `` - [Extension Kit Integration](./extension-kit/integration) — surface-agnostic APIs (events, storage, navigation) that work identically across drawer and widget --- ## Document: /docs/apps/core-concepts/extension-kit/components URL: /docs/apps/core-concepts/extension-kit/components # Extension Kit Components This guide covers the **visual components** provided by the Teachfloor Extension Kit (`@teachfloor/extension-kit`) - everything you need to build your app's user interface. ## What This Document Covers This document focuses exclusively on **UI components** for building your app's interface: - **Form Components**: TextInput, Select, Checkbox, Switch, etc. - **Layout Components**: Container, Grid, Stack, Group - **Display Components**: Button, Text, Badge, Avatar, Tabs - **Chart Components**: BarChart, LineChart - **Special Components**: SettingsView - **Setup Components**: ExtensionContextProvider, ExtensionViewLoader All components are designed to match Teachfloor's design system, ensuring your app feels native to the platform. ### Quick Reference | What you need | Where to find it | |---------------|------------------| | Buttons, Forms, Layouts, Charts | **This document** (05-components.md) | | Events, Storage, Navigation, Toasts | [Extension Kit Integration](./integration) | :::info **Looking for platform integration?** To communicate with the platform (events, storage, navigation, toasts), see the [Extension Kit Integration](./integration) guide. ::: ## Installation The Extension Kit is automatically included when you create an app with the CLI: ```bash teachfloor apps create my-app ``` To install manually: ```bash npm install @teachfloor/extension-kit react react-dom ``` ## Setup Components ### Extension Context Provider Wrap your app with the provider to enable platform context throughout your app: ```jsx import React from 'react' import ReactDOM from 'react-dom/client' import { ExtensionContextProvider } from '@teachfloor/extension-kit' import App from './App' const root = ReactDOM.createRoot(document.getElementById('root')) root.render( ) ``` **Props**: - `autoInit`: (Optional) Automatically signal app ready to platform (default: true) :::info **Accessing context data?** To use the `useExtensionContext()` hook and access platform data, see the [Extension Kit Integration](./integration#context-api) guide. ::: ### View Loader Automatically load the correct component based on viewport: ```jsx import React from 'react' import { ExtensionViewLoader } from '@teachfloor/extension-kit' import manifest from '../teachfloor-app.json' const App = () => { return ( import(`./views/${componentName}`)} /> ) } export default App ``` **Props**: - `manifest`: Your app's manifest object (required) - `componentResolver`: Function that returns a dynamic import (optional, defaults to null) - `fallback`: Loading component (optional, defaults to null) - `basePath`: Base path for components (optional, defaults to `'./'`) ## Layout Components ### Container Main content wrapper with consistent padding: ```jsx import { Container } from '@teachfloor/extension-kit'

My Content

// With props

Compact Container

``` **Props**: - `size`: `"xs"` | `"sm"` | `"md"` | `"lg"` | `"xl"` (default: `"md"`) - `p`: Padding - `m`: Margin ### Box Flexible container for layout: ```jsx import { Box } from '@teachfloor/extension-kit'

Content in a box

``` **Props**: - All standard HTML div props - Spacing props: `p`, `m`, `px`, `py`, `mx`, `my` ### Grid Responsive grid layout: ```jsx import { Grid } from '@teachfloor/extension-kit'

Half width

Half width

// Responsive columns

Responsive column

``` **Props**: - `gutter`: Gap between columns - `align`: Vertical alignment - `justify`: Horizontal alignment ### SimpleGrid Automatic grid with equal columns: ```jsx import { SimpleGrid } from '@teachfloor/extension-kit'
Item 1
Item 2
Item 3
// Responsive
Item 1
Item 2
Item 3
``` **Props**: - `cols`: Number of columns - `spacing`: Gap between items - `verticalSpacing`: Vertical gap ### Group Horizontal layout with flex: ```jsx import { Group } from '@teachfloor/extension-kit' ``` **Props**: - `spacing`: Gap between items - `position`: `"left"` | `"center"` | `"right"` | `"apart"` - `align`: Vertical alignment ## Form Components ### TextInput Single-line text input: ```jsx import { TextInput } from '@teachfloor/extension-kit' console.log(e.target.value)} /> // With validation ``` **Props**: - `label`: Input label - `placeholder`: Placeholder text - `required`: Required field - `error`: Error message - `description`: Help text - All standard input props ### Textarea Multi-line text input: ```jsx import { Textarea } from '@teachfloor/extension-kit'