Skip to content

Fix Blockly "Invalid block definition" error and add Next.js integration with fullscreen support#1

Draft
shaynlink with Copilot wants to merge 5 commits into
mainfrom
copilot/add-blockly-toolbox-configuration
Draft

Fix Blockly "Invalid block definition" error and add Next.js integration with fullscreen support#1
shaynlink with Copilot wants to merge 5 commits into
mainfrom
copilot/add-blockly-toolbox-configuration

Conversation

Copilot AI commented Oct 12, 2025

Copy link
Copy Markdown

Problem

When trying to use Blockly blocks in the toolbox, the following error occurred:

Invalid block definition for type: controls_if

This happened with the following code:

const workspace = Blockly.inject(blocklyDivRef.current, {
  toolbox: {
    kind: 'flyoutToolbox',
    contents: [
      { kind: 'block', type: 'controls_if' },
      { kind: 'block', type: 'controls_whileUntil' }
    ]
  }
});

Root Cause

The error occurred because Blockly's standard block definitions were not imported before workspace initialization. Blockly requires explicit import of block definition modules to register block types.

Solution

Added the critical imports of block definitions before Blockly.inject():

import * as Blockly from "blockly";
import "blockly/blocks";           // ← Loads ALL standard block definitions
import "blockly/javascript";       // ← Loads JavaScript code generator (optional)

For Next.js compatibility (to avoid SSR issues), these are loaded dynamically in useEffect:

"use client";

useEffect(() => {
  const initBlockly = async () => {
    const Blockly = await import("blockly");
    await import("blockly/blocks");      // Critical!
    await import("blockly/javascript");
    
    const workspace = Blockly.inject(/* ... */);
  };
  initBlockly();
}, []);

Changes Made

Core Component

  • app/_components/BlocklyBootstrap.tsx - Reusable Blockly component
    • Dynamic client-side loading to avoid Next.js SSR errors
    • Automatic block definitions import
    • Props: width, height, fullScreen
    • Proper workspace cleanup on unmount
    • TypeScript typed

Example Pages

  • app/page.tsx - Main page with Blockly workspace
  • app/fullscreen-example/page.tsx - Fullscreen mode demonstration
  • app/layout.tsx - Root application layout

Project Configuration

  • package.json - Dependencies (Blockly 12.3.1, Next.js 14, TypeScript)
  • tsconfig.json - TypeScript configuration
  • .eslintrc.json - ESLint configuration
  • next.config.js - Next.js configuration
  • .gitignore - Build artifacts and dependencies

Documentation

  • README.md - Updated with quick start guide and usage examples
  • SOLUTION.md - Focused summary of the block definition fix
  • BLOCKLY_GUIDE.md - Comprehensive 256-line guide covering:
    • Installation and setup
    • Component usage and API
    • Troubleshooting guide
    • Complete list of available blocks (logic, loops, math, text, lists, variables, functions)
    • Code generation examples
    • SSR issue resolution

Features

No more "Invalid block definition" errors - All standard Blockly blocks work correctly
Next.js compatible - Client-side dynamic loading prevents SSR issues
Fullscreen mode - Optional prop for immersive editing experience
TypeScript - Fully typed for better developer experience
Proper cleanup - Workspace disposal on component unmount
All standard blocks available - Logic, loops, math, text, lists, variables, and functions

Screenshots

Main Interface with Blocks

Blockly Interface

Fullscreen Mode

Fullscreen Mode

Usage

npm install
npm run dev

Basic usage:

import BlocklyBootstrap from "@/app/_components/BlocklyBootstrap";

export default function MyPage() {
  return <BlocklyBootstrap width="100%" height="600px" />;
}

Fullscreen mode:

<BlocklyBootstrap fullScreen={true} />

Testing

  • ✅ TypeScript compilation passes with no errors
  • ✅ ESLint passes with no warnings
  • ✅ Production build successful with optimization
  • ✅ Both normal and fullscreen modes tested and working
  • ✅ All standard blocks load correctly without errors
  • ✅ Browser console shows no errors

Key Takeaway

The fix is simple but critical: always import blockly/blocks before using any blocks in your toolbox. The order matters:

  1. Import Blockly core
  2. Import block definitions (blockly/blocks)
  3. Import code generators if needed (blockly/javascript)
  4. Then initialize workspace with Blockly.inject()

This is now handled automatically in the BlocklyBootstrap component.

Original prompt
    const workspace = Blockly.inject(blocklyDivRef.current, {
      toolbox: {
        kind: 'flyoutToolbox',
        contents: [
          {
            kind: 'block',
            type: 'controls_if',
          },
          {
            kind: 'block',
            type: 'controls_whileUntil'
          }
        ]
      },

      Invalid block definition for type: controls_if

The following is a snapshot of a chat conversation between a user and an AI coding assistant. Prioritize later messages in the conversation.
User: Aide moi à configurer Blocky
AI: Je vais d'abord créer une todo list pour organiser le travail (lecture du fichier existant, vérifier les dépendances, mettre à jour le composant et tester). Ensuite je lirai le fichier
AI: pour voir l'état actuel et proposer des modifications. Expected outcome: todo list created and fichier lu.
AI: Je vais lire le fichier
AI: pour comprendre l'implémentation actuelle et repérer ce qui doit être adapté pour Next.js (attendu: contenu du fichier).
AI: Je marque la lecture du fichier comme terminée et je passe à la vérification des dépendances (recherche de blockly dans
AI: ). Ensuite j'ouvrirai
AI: .
AI: Je vais mettre à jour la todo list (marquer la vérification des dépendances terminée et passer la modification du composant en cours), puis modifier
AI: pour charger Blockly dynamiquement, stocker/vider le workspace proprement et éviter les imports côté serveur. Ensuite je vérifierai les erreurs de build. Expected outcome: fichier mis à jour et erreurs rapportées.
AI: Je vais appliquer un patch pour améliorer
AI: : enlever l'import statique global de Blockly (qui peut s'exécuter côté serveur) et le charger dynamiquement dans useEffect, gérer proprement la destruction du workspace et exposer un prop optionnel pour la taille. Outcome: fichier mis à jour.
AI:


AI: 

AI: I will fix the lint/type issues: make Props readonly, tighten workspaceRef typing to 'Blockly.WorkspaceSvg | null' by importing types via dynamic import type or using unknown and casting, remove unnecessary eslint-disable and provide proper ts-expect-error comments, and handle the catch by logging. I'll update the file accordingly.
AI:


AI: 

AI: I'll update the component to use a type-only import for WorkspaceSvg, avoid 'any' and remove ts-expect-error comments by casting the dynamic import to a narrow interface using unknown. This should satisfy the linter/type rules. I'll apply the patch now.
AI:


AI: 

AI: Progress update: I read the component and dependencies, then refactored
AI: to dynamically load Blockly on the client, type the workspace, and handle disposal cleanly. Next I'll run TypeScript/ESLint checks to ensure there are no remaining errors; I'll use the task runner to run a quick TypeScript build or run pnpm -w isn't necessary — I'll run pnpm -w not needed. I'll run pnpm -v? Instead I'll run pnpm -P? The workspace uses pnpm; I'll run a TypeScript check with pnpm dlx tsc --noEmit or run pnpm -w... I'll run pnpm -w? Simpler: run pnpm -w is wrong. I'll run pnpm -w... Hmm. Better: run pnpm -w --silent install? The guidance: use run_in_terminal. I'll run pnpm install then pnpm dev partial. But running full dev may be slow. The requirement: run typecheck/build. Use pnpm dlx tsc --noEmit to run TS. I'll run pnpm dlx tsc --noEmit in workspace root.
AI: The terminal command produced no visible output (likely because the environment didn't run the command). I'll instead run the project's lint script pnpm -w is unnecessary; run pnpm -w? The workspace has pnpm; I'll run pnpm -w dlx tsc --noEmit? Simpler: run pnpm dlx tsc --noEmit again with full path. I'll run it again.
AI: The terminal returned no output again—this environment's terminal may not show output for these commands. I'll instead run the project's dev script to surface any runtime errors. I'll run pnpm dev which starts Next dev; it may be long-running but will show build errors. I'll run it in background so we can capture initial build output.
AI: Progress: I updated the component, ran the dev server in background and saw it started on an alternate port (3001) with no build errors reported so far. Next I'll update the todo list: mark the component adaptation completed and add the steps for installation instructions as in-progress. Then I'll prepare a short guidance message in French explaining how to install and test Blockly locally and any caveats.
AI: J'ai mis en place la base pour intégrer Blockly côté client et vérifié rapidement le build/dev. Voici ce que j'ai fait, ce que je recommande ensuite, et comment tester localement.

Actions réalisées

  • Lu et analysé
    AI: .
  • Vérifié que blockly est déjà présent dans
    AI: (version ^12.3.1).
  • Refactor du composant
    AI: pour :
    • Charger Blockly dynamiquement uniquement côté client (import dynamique dans useEffect).
    • Éviter l...

Created from VS Code via the GitHub Pull Request extension.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 4 commits October 12, 2025 15:24
…nitions

Co-authored-by: shaynlink <38408035+shaynlink@users.noreply.github.com>
Co-authored-by: shaynlink <38408035+shaynlink@users.noreply.github.com>
Co-authored-by: shaynlink <38408035+shaynlink@users.noreply.github.com>
Co-authored-by: shaynlink <38408035+shaynlink@users.noreply.github.com>
Copilot AI changed the title [WIP] Add configuration for Blockly toolbox blocks Fix Blockly "Invalid block definition" error and add Next.js integration with fullscreen support Oct 12, 2025
Copilot AI requested a review from shaynlink October 12, 2025 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants