Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Canvas LMS

Connect Bolt.new to Canvas LMS by building a Next.js API route that proxies Canvas REST API calls using your institution's API token. Store credentials in environment variables, never in client code. Outbound API calls work in Bolt's WebContainer during development; deploy to Netlify or Vercel to expose public endpoints for production course management dashboards and grade tools.

What you'll learn

  • How to authenticate with the Canvas REST API using a personal access token
  • How to build a server-side API route in Bolt.new that proxies Canvas data safely
  • How to display courses, assignments, and grades in a React dashboard
  • How to handle Canvas pagination for large course rosters
  • How to deploy your Canvas dashboard to Netlify with production environment variables
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate14 min read25 minutesOtherApril 2026RapidDev Engineering Team
TL;DR

Connect Bolt.new to Canvas LMS by building a Next.js API route that proxies Canvas REST API calls using your institution's API token. Store credentials in environment variables, never in client code. Outbound API calls work in Bolt's WebContainer during development; deploy to Netlify or Vercel to expose public endpoints for production course management dashboards and grade tools.

Build a Canvas LMS Dashboard in Bolt.new

Canvas LMS powers course management for over 30 million learners worldwide. Its REST API gives developers access to virtually everything instructors and students see in the UI: course listings, assignment details, submission statuses, grade books, enrollment data, and discussion threads. Combining the Canvas API with Bolt.new lets educators, EdTech startups, and institutional developers build custom dashboards, grade-tracking widgets, and assignment workflow tools without touching the Canvas UI.

Bolt.new's architecture fits the Canvas API well. Canvas requires OAuth 2.0 for production apps or personal access tokens for internal tools — both are credentials that must stay server-side. A Next.js API route running in Bolt.new's WebContainer proxies all Canvas calls, keeping the token out of client bundles. The React frontend fetches from your own API route and renders data in any layout you design.

One important constraint to plan around: Canvas supports outbound webhooks (Live Events) to notify your app about submissions and grade changes. These webhooks require a publicly accessible URL — something Bolt.new's WebContainer cannot provide during development. You will build and test read operations in Bolt's preview, then deploy to Netlify or Vercel before configuring Canvas Live Events to point at your endpoint. This two-phase workflow is standard for all webhook-dependent Canvas integrations.

Integration method

Bolt Chat + API Route

Canvas LMS exposes a comprehensive REST API that accepts Bearer token authentication. In Bolt.new you build a Next.js API route that holds your Canvas API token server-side, then fetch course data, grades, and assignments and surface them in React components. Outbound calls work in the WebContainer preview; incoming webhooks from Canvas require a deployed URL.

Prerequisites

  • A Canvas LMS account with API access (instructor, admin, or student account at a Canvas-enabled institution)
  • A Canvas personal access token — generate one in Canvas Account Settings → Approved Integrations → New Access Token
  • Your Canvas instance base URL (e.g., https://yourschool.instructure.com)
  • A Bolt.new account with a new Next.js project open
  • A Netlify account for deployment and webhook testing

Step-by-step guide

1

Generate a Canvas Personal Access Token

Before writing any code, you need a Canvas API token. Log in to your Canvas instance and navigate to Account (your avatar, top-left) → Settings. Scroll down to the 'Approved Integrations' section and click 'New Access Token.' Give it a descriptive name like 'Bolt Dashboard Dev' and optionally set an expiry date. Click 'Generate Token' and copy the token immediately — Canvas only shows it once. Also note your institution's Canvas base URL (e.g., https://canvas.university.edu). You will need both values as environment variables. For production applications intended for use by many users, Canvas supports OAuth 2.0 developer keys — your Canvas admin must create a developer key in the admin panel. Personal access tokens are appropriate for internal tools, prototypes, and single-user dashboards. Never commit either the token or the base URL to a public repository; treat the API token with the same care as a database password.

Pro tip: Canvas tokens can be scoped — when creating your token, click 'Show Token Expiry' and limit the expiry to 90 days for security. For production multi-user apps, ask your Canvas admin to set up an OAuth 2.0 developer key instead.

Expected result: You have a Canvas API token string and your institution's base URL ready to add to your environment variables.

2

Set Up Environment Variables and Prompt Bolt to Generate the Integration

In your Bolt.new project, open the terminal and create a .env file at the project root. Add two variables: CANVAS_API_TOKEN with your token value and CANVAS_BASE_URL with your institution's Canvas domain. In Next.js, server-side environment variables without a NEXT_PUBLIC_ prefix are never bundled into client code — this is exactly what you want for API credentials. Once the .env file is saved, use Bolt's AI chat to generate the API route and frontend components. The AI will read your project structure and generate code that references process.env.CANVAS_API_TOKEN automatically. After you paste the prompt, Bolt will create the API route file and the frontend page. Review the generated code to confirm the token is only accessed in the API route, never in any client component file. If you see process.env.CANVAS_API_TOKEN in a file under the app/ directory that is not inside app/api/, ask Bolt to move that logic to the API route.

Bolt.new Prompt

Create a Canvas LMS integration in this Next.js project. Build an API route at app/api/canvas/courses/route.ts that fetches the list of courses for the current user from the Canvas REST API. Use process.env.CANVAS_BASE_URL as the base URL and process.env.CANVAS_API_TOKEN as the Bearer token. Handle Canvas pagination by following the Link header. Return the courses as JSON. Then create a React page at app/canvas/page.tsx that calls this API route and displays the courses in a responsive card grid with course name, course code, and enrollment type.

Paste this in Bolt.new chat

.env
1# .env file add to project root, never commit to git
2CANVAS_API_TOKEN=your_canvas_token_here
3CANVAS_BASE_URL=https://yourschool.instructure.com

Pro tip: Add .env to your .gitignore file immediately. Bolt usually does this automatically for Next.js projects, but double-check before pushing to GitHub.

Expected result: Bolt generates an API route file and a React page. The project structure shows app/api/canvas/courses/route.ts and app/canvas/page.tsx.

3

Review and Refine the Generated API Route

Bolt's generated API route should handle authentication, make the Canvas API request, and return data to the frontend. Open app/api/canvas/courses/route.ts and verify the structure. Key things to check: the Authorization header uses 'Bearer' followed by the token (not 'Token' — Canvas accepts both but Bearer is more standard); the URL correctly combines CANVAS_BASE_URL with the API path; and error responses from Canvas are forwarded to the client with appropriate HTTP status codes. Canvas's API returns paginated results using Link headers in the response — a common oversight in AI-generated code is fetching only the first page of results. If your institution has more than 10 courses, you need pagination logic. The code below shows a production-ready API route with pagination support. Canvas also rate-limits API calls; for high-frequency polling apps, implement caching using Next.js's built-in fetch caching with a revalidate interval. The WebContainer preview will successfully make outbound calls to Canvas's servers, so you can verify the integration works before deploying.

Bolt.new Prompt

Update the Canvas API route to handle pagination by following the Link header in Canvas API responses. Keep fetching pages until there is no 'next' link, then return all results combined. Also add error handling that returns a 500 status with an error message if the Canvas API call fails.

Paste this in Bolt.new chat

app/api/canvas/courses/route.ts
1// app/api/canvas/courses/route.ts
2import { NextResponse } from 'next/server';
3
4interface CanvasCourse {
5 id: number;
6 name: string;
7 course_code: string;
8 enrollment_term_id: number;
9 workflow_state: string;
10}
11
12async function fetchAllPages<T>(url: string, token: string): Promise<T[]> {
13 const results: T[] = [];
14 let nextUrl: string | null = url;
15
16 while (nextUrl) {
17 const response = await fetch(nextUrl, {
18 headers: {
19 Authorization: `Bearer ${token}`,
20 'Content-Type': 'application/json',
21 },
22 });
23
24 if (!response.ok) {
25 throw new Error(`Canvas API error: ${response.status} ${response.statusText}`);
26 }
27
28 const data: T[] = await response.json();
29 results.push(...data);
30
31 // Parse the Link header for pagination
32 const linkHeader = response.headers.get('Link');
33 nextUrl = null;
34 if (linkHeader) {
35 const match = linkHeader.match(/<([^>]+)>;\s*rel="next"/);
36 if (match) nextUrl = match[1];
37 }
38 }
39
40 return results;
41}
42
43export async function GET() {
44 const token = process.env.CANVAS_API_TOKEN;
45 const baseUrl = process.env.CANVAS_BASE_URL;
46
47 if (!token || !baseUrl) {
48 return NextResponse.json(
49 { error: 'Canvas credentials not configured' },
50 { status: 500 }
51 );
52 }
53
54 try {
55 const courses = await fetchAllPages<CanvasCourse>(
56 `${baseUrl}/api/v1/courses?enrollment_state=active&per_page=50`,
57 token
58 );
59
60 return NextResponse.json({ courses });
61 } catch (error) {
62 const message = error instanceof Error ? error.message : 'Unknown error';
63 return NextResponse.json({ error: message }, { status: 500 });
64 }
65}

Pro tip: Canvas API endpoints follow the pattern /api/v1/[resource]. The full API documentation is at your-institution.instructure.com/doc/api/live — replace 'your-institution' with your Canvas domain.

Expected result: The API route handles pagination and returns all active courses. Opening /api/canvas/courses in the Bolt preview browser tab returns a JSON response with your Canvas courses.

4

Build the Frontend Dashboard

With a working API route, prompt Bolt to build a polished React dashboard that consumes it. The frontend page fetches from /api/canvas/courses using the native fetch API inside a useEffect hook or a library like SWR for automatic revalidation. Canvas courses include useful metadata: the name, course_code, current_grade and current_score if the user is enrolled as a student, and the number of students if the user is an instructor. Design the dashboard to show the most actionable information first. For a student view, upcoming assignment due dates pulled from /api/v1/courses/:id/assignments are more useful than raw grade numbers. For an instructor view, submission counts and ungraded work counts drive daily workflow. You can add multiple API routes — one for courses, one for assignments, one for announcements — and compose them in a tabbed layout on the frontend. Bolt's AI is excellent at generating Tailwind CSS layouts; describe the card design, grid structure, and color scheme you want and it will produce clean markup. Keep each component file under 300 lines to stay well within Bolt's context window limits and avoid AI confusion during subsequent edits.

Bolt.new Prompt

Update the Canvas dashboard page at app/canvas/page.tsx. Add a second API route at app/api/canvas/assignments/route.ts that accepts a courseId query parameter and fetches upcoming assignments for that course, returning title, due_at, points_possible, and submission status. On the dashboard page, when a user clicks a course card, show a slide-out panel listing that course's upcoming assignments sorted by due date. Style everything with Tailwind CSS using a clean academic aesthetic — white cards, subtle shadows, blue accent color.

Paste this in Bolt.new chat

app/canvas/page.tsx
1// app/canvas/page.tsx
2'use client';
3
4import { useEffect, useState } from 'react';
5
6interface Course {
7 id: number;
8 name: string;
9 course_code: string;
10 workflow_state: string;
11}
12
13export default function CanvasDashboard() {
14 const [courses, setCourses] = useState<Course[]>([]);
15 const [loading, setLoading] = useState(true);
16 const [error, setError] = useState<string | null>(null);
17
18 useEffect(() => {
19 fetch('/api/canvas/courses')
20 .then((res) => res.json())
21 .then((data) => {
22 if (data.error) throw new Error(data.error);
23 setCourses(data.courses);
24 })
25 .catch((err) => setError(err.message))
26 .finally(() => setLoading(false));
27 }, []);
28
29 if (loading) return <div className="p-8 text-center">Loading your courses...</div>;
30 if (error) return <div className="p-8 text-red-600">Error: {error}</div>;
31
32 return (
33 <div className="max-w-5xl mx-auto p-8">
34 <h1 className="text-3xl font-bold text-gray-900 mb-6">My Courses</h1>
35 <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
36 {courses.map((course) => (
37 <div key={course.id} className="bg-white rounded-lg shadow p-5 border border-gray-100 hover:shadow-md transition-shadow">
38 <div className="text-xs font-mono text-blue-600 mb-1">{course.course_code}</div>
39 <h2 className="text-base font-semibold text-gray-800">{course.name}</h2>
40 </div>
41 ))}
42 </div>
43 </div>
44 );
45}

Pro tip: Canvas returns ISO 8601 timestamps for due dates. Use new Date(due_at).toLocaleDateString() to format them for display, or a library like date-fns for relative time labels like 'due in 3 days'.

Expected result: The dashboard page renders a grid of Canvas course cards. Clicking a card shows assignments for that course.

5

Deploy to Netlify and Configure Production Environment Variables

The Bolt.new WebContainer successfully makes outbound calls to Canvas, so your read-only dashboard works in preview. However, if you plan to use Canvas Live Events (webhooks for submission notifications) or if you want to share the dashboard with other users, you need a deployed URL. Connect your Bolt project to Netlify through Settings → Applications → Netlify → Connect. Bolt will build the Next.js project and deploy it to a *.netlify.app domain. Once deployed, navigate to the Netlify dashboard for your site, go to Site Configuration → Environment Variables, and add CANVAS_API_TOKEN and CANVAS_BASE_URL with your production values. Click 'Deploy site' in Netlify to trigger a fresh build with the new environment variables. Critical WebContainer note: Canvas Live Events webhooks cannot reach the Bolt preview URL because WebContainers do not accept incoming HTTP connections. The Live Events feature — which notifies your app when assignments are submitted, grades are posted, or course enrollments change — only works once you have a stable, publicly accessible URL from your Netlify deployment. Register your Netlify URL in Canvas Admin → Developer Keys → Live Events to enable real-time notifications.

Bolt.new Prompt

Add a Canvas Live Events webhook handler at app/api/canvas/webhook/route.ts. The endpoint should accept POST requests, verify the request has a valid Authorization header matching a CANVAS_WEBHOOK_SECRET environment variable, parse the Canvas event payload, log the event type and affected resource, and return a 200 OK response. Include handling for submission_created, submission_updated, and grade_change event types.

Paste this in Bolt.new chat

app/api/canvas/webhook/route.ts
1// app/api/canvas/webhook/route.ts
2import { NextResponse } from 'next/server';
3
4interface CanvasLiveEvent {
5 metadata: {
6 event_name: string;
7 event_time: string;
8 context_type: string;
9 context_id: string;
10 };
11 body: Record<string, unknown>;
12}
13
14export async function POST(request: Request) {
15 // Verify the webhook secret from Canvas
16 const authHeader = request.headers.get('Authorization');
17 const expectedSecret = process.env.CANVAS_WEBHOOK_SECRET;
18
19 if (!expectedSecret || authHeader !== `Bearer ${expectedSecret}`) {
20 return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
21 }
22
23 const event: CanvasLiveEvent = await request.json();
24 const eventName = event.metadata?.event_name;
25
26 console.log(`Canvas Live Event received: ${eventName}`, {
27 context_type: event.metadata?.context_type,
28 context_id: event.metadata?.context_id,
29 event_time: event.metadata?.event_time,
30 });
31
32 switch (eventName) {
33 case 'submission_created':
34 case 'submission_updated':
35 // Process new or updated submission
36 console.log('Submission event:', event.body);
37 break;
38 case 'grade_change':
39 // Process grade change
40 console.log('Grade change event:', event.body);
41 break;
42 default:
43 console.log('Unhandled event type:', eventName);
44 }
45
46 // Always return 200 quickly — Canvas retries on non-2xx responses
47 return NextResponse.json({ received: true });
48}

Pro tip: After deploying, add CANVAS_WEBHOOK_SECRET to Netlify's environment variables with a strong random string, then register your webhook URL (https://yoursite.netlify.app/api/canvas/webhook) in Canvas Admin → Developer Keys → Live Events.

Expected result: Your Canvas dashboard is live on a *.netlify.app URL. Canvas Live Events webhook handler is accessible at /api/canvas/webhook and ready for registration in Canvas admin.

Common use cases

Student Grade Dashboard

Build a clean, modern interface that shows a student all their current courses, assignment due dates, and grades in one view. Canvas's own UI can feel dense; a custom dashboard can highlight what matters — upcoming deadlines, missing submissions, and current GPA — with better visual hierarchy.

Bolt.new Prompt

Build a Canvas LMS student dashboard in Next.js. Create an API route at /api/canvas/courses that fetches all enrolled courses for a user using a Canvas personal access token stored in process.env.CANVAS_API_TOKEN and process.env.CANVAS_BASE_URL. Then build a React page that displays course names, current grades, and upcoming assignment due dates in a card grid layout using Tailwind CSS.

Copy this prompt to try it in Bolt.new

Instructor Assignment Submission Tracker

Give instructors a live view of which students have submitted an assignment, who is late, and grade distribution without navigating Canvas's SpeedGrader. A Bolt.new app can pull submission data from the Canvas API and render a filterable table sorted by submission status.

Bolt.new Prompt

Create a Next.js app with a Canvas LMS submission tracker for instructors. Add an API route at /api/canvas/submissions that accepts a courseId and assignmentId query param, fetches all submissions from the Canvas API using Bearer token auth, and returns submission status and scores. Display the results in a sortable table with columns for student name, submission status, submitted-at time, and score.

Copy this prompt to try it in Bolt.new

Course Announcement Feed

Aggregate announcements from multiple Canvas courses into a single chronological feed. Students who manage several courses often miss announcements buried in individual course pages; a unified feed with unread indicators improves engagement and reduces missed communications.

Bolt.new Prompt

Build a Canvas LMS announcement aggregator in Next.js. Create an API route that fetches announcements from all active courses for the authenticated user using the Canvas REST API. Display them in a timeline UI sorted by posted date, with the course name shown as a badge on each announcement. Use process.env.CANVAS_API_TOKEN for authentication.

Copy this prompt to try it in Bolt.new

Troubleshooting

API route returns 401 Unauthorized from Canvas

Cause: The Canvas personal access token is expired, has been revoked, or is being sent with the wrong authentication format.

Solution: Go to Canvas Account Settings → Approved Integrations and check if your token is still listed. Generate a new token if needed. Verify the Authorization header in your API route uses exactly 'Bearer YOUR_TOKEN' — Canvas also supports 'Token YOUR_TOKEN' but some endpoints require Bearer. Confirm CANVAS_API_TOKEN in your .env file has no extra whitespace or quote characters.

typescript
1// Correct header format
2headers: {
3 Authorization: `Bearer ${process.env.CANVAS_API_TOKEN}`,
4 'Content-Type': 'application/json',
5}

API route returns an empty array even though courses exist in Canvas

Cause: The Canvas API requires an enrollment_state parameter to include active courses, and the default enrollment_type filter may exclude your account type.

Solution: Add enrollment_state=active to your query parameters. If you are a teacher rather than a student, also add enrollment_type[]=teacher to the request. Check the Canvas API docs for your specific access level.

typescript
1const url = `${baseUrl}/api/v1/courses?enrollment_state=active&enrollment_type[]=student&enrollment_type[]=teacher&per_page=50`;

Canvas webhook endpoint returns errors or Canvas stops sending events after deployment

Cause: Canvas Live Events webhooks cannot reach Bolt's WebContainer preview URL because the WebContainer does not accept incoming HTTP connections from the public internet.

Solution: Deploy to Netlify or Vercel first to get a stable public URL. Register the deployed URL (not the Bolt preview URL) in Canvas Admin → Developer Keys → Live Events. Webhooks must point to https://yoursite.netlify.app/api/canvas/webhook. Verify your CANVAS_WEBHOOK_SECRET environment variable is set in the Netlify dashboard, not just in the local .env file.

CORS error when calling Canvas API directly from a React component

Cause: Canvas's API does not allow cross-origin requests from arbitrary browser origins. Calling the Canvas API directly from client-side React code triggers a CORS block.

Solution: All Canvas API calls must go through the Next.js API route (server-side), never directly from client components. The API route in app/api/ runs server-side and is not subject to browser CORS restrictions.

typescript
1// Wrong — calling Canvas API directly from a React component
2const res = await fetch(`${process.env.NEXT_PUBLIC_CANVAS_BASE_URL}/api/v1/courses`);
3
4// Correct — call your own API route from the client
5const res = await fetch('/api/canvas/courses');

Best practices

  • Always store CANVAS_API_TOKEN and CANVAS_BASE_URL as server-side environment variables — never use NEXT_PUBLIC_ prefix for Canvas credentials
  • Implement Canvas API pagination by following the Link header — never assume a single response contains all results
  • Cache Canvas API responses with Next.js fetch caching (next: { revalidate: 300 }) to avoid hitting Canvas rate limits on frequently accessed pages
  • For multi-user apps, implement Canvas OAuth 2.0 rather than sharing a single personal access token — each user authenticates with their own Canvas credentials
  • Test read-only operations in Bolt's preview, but always deploy to Netlify before testing Canvas Live Events webhooks
  • Set a reasonable expiry on Canvas personal access tokens (90 days) and build a clear error message when the token expires so users know to regenerate it
  • Use TypeScript interfaces that match the Canvas API response shapes to catch data structure changes early

Alternatives

Frequently asked questions

Does Bolt.new work with Canvas LMS?

Yes. Canvas LMS has a comprehensive REST API that works perfectly with Bolt.new's Next.js API routes. You store your Canvas API token as a server-side environment variable, build an API route to proxy requests, and display the data in React components. Outbound calls to Canvas work in Bolt's WebContainer preview; incoming webhooks require a deployed URL.

Can I display live grade updates from Canvas in a Bolt.new app?

You can fetch current grades at any time via the Canvas API. For real-time grade change notifications, Canvas offers Live Events webhooks that POST to your endpoint when grades change. These webhooks require a deployed URL on Netlify or Vercel since Bolt's WebContainer cannot receive incoming HTTP traffic. Once deployed, register your /api/canvas/webhook endpoint in Canvas Admin.

How do I connect Bolt.new to Canvas for multiple users?

Personal access tokens are per-user and not suitable for multi-user apps. For applications where different people log in with their own Canvas accounts, you need to implement Canvas OAuth 2.0. Ask your Canvas administrator to create a Developer Key, then build an OAuth flow in your Bolt.new app. Each user's access token is stored after OAuth and used for their subsequent API calls.

Can I use Canvas LMS in Bolt.new during development without deploying?

Yes — all read operations (fetching courses, assignments, grades) work in Bolt's WebContainer preview because they are outbound HTTP calls from the server-side API route. The only operations that require deployment are Canvas Live Events webhooks, which need a stable public URL to deliver event payloads.

What Canvas API features are most useful in a Bolt.new dashboard?

The most commonly used Canvas API endpoints for dashboards are /api/v1/courses for course listings, /api/v1/courses/:id/assignments for assignment data, /api/v1/courses/:id/enrollments for student roster, and /api/v1/courses/:id/grades for grade books. Each returns rich JSON with all the data you see in the Canvas UI.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.