PlaycademyPlaycademy

Develop

Local development with the Playcademy Vite plugin

Overview

The Vite plugin automatically starts a local development environment with sandbox and backend servers.

Starting Development

Run your standard Vite dev server:

bun dev
npm run dev
pnpm dev
yarn dev

What happens next?

The plugin automatically

  1. Starts local sandbox on port 4321
  2. Starts backend server on port 8788 (if configured)
  3. Shows startup info in console
Command
$ bun dev
Output
VITE v1.2.3➜ Local: http://localhost:5173/➜ Network: use --host to exposePLAYCADEMY v1.2.3➜ Project: my-project➜ Sandbox: http://localhost:4321/api➜ Backend: http://localhost:5173/api (via 8788)

Additional Servers

  • Backend line appears if you have custom routes configured

Local Development Servers

Sandbox Server

The sandbox simulates the Playcademy Platform API, using mock data for convenience:

FeatureBehavior
UserMock user session
CreditsStarting balance (1000)
InventoryEmpty, persists in sandbox database
StatePersists in sandbox database
LevelsStarts at level 1

Your SDK calls connect to the sandbox during development:

import { PlaycademyClient } from '@playcademy/sdk'

const client = await PlaycademyClient.init() // Connects to sandbox in dev

Sandbox configuration:

vite.config.ts
playcademy({
    sandbox: { recreateDb: true },
})
vite.config.ts
playcademy({
    sandbox: { memoryOnly: true },
})
vite.config.ts
playcademy({
    sandbox: { seed: false },
})

Backend Server

The backend server starts automatically if you have any integrations:

playcademy.config.js
export default {
    name: 'My Project',
    integrations: {
        database: { directory: 'db' },
        kv: true,
        // Any integration enables the backend
    },
}

No integrations? No need for a backend server.

Learn More

See the CLI Development Guide for detailed information about the backend server.


User Authentication

In Custom Routes, you can access the authenticated platform user via c.get('playcademyUser'):

server/api/user.ts
export async function GET(c: Context) {
    const playcademyUser = c.get('playcademyUser')

    if (!playcademyUser) {
        return c.json({ error: 'Not authenticated' }, 401)
    }

    return c.json({
        userId: playcademyUser.sub,
        message: `Hello, ${playcademyUser.name}!`,
    })
}

Platform Mode Required

playcademyUser is only populated when:

  1. The plugin is running in Platform Mode
  2. Requests are made via sdk.backend (not plain fetch)

In Standalone Mode, playcademyUser will be null.

Standalone Authentication

For user accounts outside the Playcademy platform, set up the Authentication Integration.


Plugin Modes

The Vite plugin supports two modes:

This simulates the full Playcademy platform experience.

  1. Mock platform API (sandbox)
  2. Backend server for integrations
  3. Platform shell UI with dev badge
vite.config.ts
playcademy({
    mode: 'platform', // Default
})

Use this when testing your project without Playcademy platform features.

vite.config.ts
playcademy({
    mode: 'standalone',
})

Fast Switching

Press m + enter in your terminal while the Vite dev server is running to toggle between platform and standalone modes.


Timeback

Configure Timeback courses, enrollments, and user roles for local development.

Use mock data for quick iteration, or connect to real Timeback credentials for integration testing.

Coming Soon

A new @timeback/local package is in active development.

Once released, this will provide a significant improvement to the local development experience.

Configuration

vite.config.ts
playcademy({
    timeback: {
        // id: auto-generated mock ID (default)
        // id: 'tb_abc123' - use a real Timeback ID for integration testing
        courses: {
            'FastMath:3': 'mock', // 'mock' generates fake course ID or omit the course for the same effect
            'FastMath:4': '00000011-0001-0001-0001-000000000001', // or use real course ID for integration testing
        },
        // role: 'student' (default) - cycle with 't' hotkey
    },
})

Options

By default, all courses from your playcademy.config.js are automatically enrolled with mock IDs.

vite.config.ts
export default defineConfig({
    plugins: [
        playcademy(), // All courses enrolled automatically!
    ],
})

This is the same as:

vite.config.ts
export default defineConfig({
    plugins: [
        playcademy({
            timeback: {
                courses: {
                    'FastMath:3': 'mock', // must match a course in your config
                    'FastMath:4': 'mock', // must match a course in your config
                },
            },
        }),
    ],
})

Test specific grade enrollment by excluding courses. Use null or false to exclude:

playcademy.config.js
export default {
    name: 'My Project',
    integrations: {
        timeback: {
            courses: [
                { subject: 'FastMath', grade: 3 },
                { subject: 'FastMath', grade: 4 },
                { subject: 'FastMath', grade: 5 },
            ],
        },
    },
}
vite.config.ts
export default defineConfig({
    plugins: [
        playcademy({
            timeback: {
                courses: {
                    // FastMath:3 is enrolled by default
                    'FastMath:4': null, // not enrolled yet
                    'FastMath:5': null, // not enrolled yet
                },
            },
        }),
    ],
})

The example above simulates a student enrolled in grade 3 only: useful for testing grade progression flows.

Test with a specific school or district by providing organization details:

vite.config.ts
playcademy({
    timeback: {
        organization: {
            id: 'PLAYCADEMY',
            name: 'Playcademy Studios',
            type: 'department', // 'school' | 'district' | 'department' | etc.
        },
    },
})

Omit the organization property (or set to 'mock') for a generic Playcademy organization.

Test different user experiences by changing the role.

vite.config.ts
playcademy({
    timeback: {
        role: 'teacher',
    },
})

Role Cycling

You can press t in the terminal to cycle roles when Vite is running.

For integration testing against real Timeback services, provide actual student and course IDs:

vite.config.ts
playcademy({
    timeback: {
        id: '00000011-0001-0001-0001-000000000000', // real student sourcedId
        courses: {
            'FastMath:2': '00000022-0002-0002-0002-000000000002', // real course sourcedId
            'FastMath:3': '00000033-0003-0003-0003-000000000003', // real course sourcedId
        },
    },
})

To test against live Timeback services, you must also configure your .env file with credentials:

.env
# Required: Timeback API credentials
TIMEBACK_API_CLIENT_ID=your-client-id
TIMEBACK_API_CLIENT_SECRET=your-client-secret
TIMEBACK_API_AUTH_URL=https://auth.example.com

# Required: OneRoster and Caliper endpoints
TIMEBACK_ONEROSTER_API_URL=https://oneroster.example.com
TIMEBACK_CALIPER_API_URL=https://caliper.example.com

See Timeback Authentication and Endpoints for details.

OptionDescriptionDefault
idTimeback student IDauto-generated mock ID
roleUser role: student, parent, teacher, administrator, guardian'student'
organizationOrganization config: 'mock' or { id, name, type }'mock'
coursesOverride specific courses: 'mock', real ID, or null/false to excludeauto-enrolled from config

Course Keys Must Match

The courses entries (e.g., 'FastMath:3') must match courses defined in your playcademy.config.js:

playcademy.config.js
timeback: {
    courses: [
        { subject: 'FastMath', grade: 3 }, // → 'FastMath:3' in vite.config.ts
        { subject: 'FastMath', grade: 4 }, // → 'FastMath:4' in vite.config.ts
    ],
}

Role Cycling

Press t + enter in the terminal to cycle through Timeback roles during development:

12:00:00 PM [playcademy] (timeback) student → parent
12:00:01 PM [playcademy] (timeback) parent → teacher
12:00:02 PM [playcademy] (timeback) teacher → administrator
12:00:03 PM [playcademy] (timeback) administrator → student

Learn More

See the Timeback Integration guide for more on developing with Timeback in your app.


CLI Hotkeys

This plugin provides keyboard shortcuts in the terminal during development:

KeyDescription
mToggle between platform and standalone modes
dRecreate sandbox database (resets to fresh seeded state)
pCycle platform user role (player → developer → admin)
tCycle Timeback role (student → parent → teacher → admin → guardian)

Database Recreation

Some configuration changes require recreating the sandbox database to take effect.

Press d after changing options like timeback.id, timeback.organization, or timeback.courses in your vite.config.ts.


Debugging

Verbose Logging

Enable verbose logging to see all sandbox activity:

vite.config.ts
playcademy({ sandbox: { verbose: true } })

This shows:

  1. All API calls and responses
  2. Sandbox startup details
  3. Full error stack traces

Log Levels

Control the amount of logging with the logLevel option:

vite.config.ts
playcademy({
    sandbox: {
        logLevel: 'debug', // 'debug' | 'info' | 'warn' | 'error'
    },
})
Log LevelDescription
debugAll logs including detailed debug information
infoGeneral information (default)
warnWarnings and errors only
errorErrors only

What's Next?

On this page