diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml
new file mode 100644
index 0000000..acd5c4a
--- /dev/null
+++ b/.github/workflows/test_examples.yml
@@ -0,0 +1,100 @@
+on:
+  pull_request:
+    paths:
+      - '**.py'
+  workflow_dispatch:
+
+name: Test Examples
+
+jobs:
+  build-examples:
+    strategy:
+      matrix:
+        manim: [manim, manimgl]
+        os: [macos-latest, ubuntu-latest, windows-latest]
+        pyversion: ['3.7', '3.8', '3.9', '3.10']
+        exclude:
+        # excludes manimgl on Windows because if throws errors
+        # related to OpenGL, which seems hard to fix:
+        # Your graphics drivers do not support OpenGL 2.0.
+        - os: windows-latest
+          manim: manimgl
+        # manimgl actually requires Python >= 3.8, see:
+        # https://github.com/3b1b/manim/issues/1808
+        - manim: manimgl
+          pyversion: '3.7'
+        # We only test Python 3.10 on Windows and MacOS
+        - os: windows-latest
+          pyversion: '3.7'
+        - os: windows-latest
+          pyversion: '3.8'
+        - os: windows-latest
+          pyversion: '3.9'
+        - os: macos-latest
+          pyversion: '3.7'
+        - os: macos-latest
+          pyversion: '3.8'
+        - os: macos-latest
+          pyversion: '3.9'
+    runs-on: ${{ matrix.os }}
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v3
+      - name: Install Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.pyversion }}
+      - name: Append to Path on MacOS and Ubuntu
+        if: matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest'
+        run: echo "${HOME}/.local/bin" >> $GITHUB_PATH
+      - name: Append to Path on Windows
+        if: matrix.os == 'windows-latest'
+        run: echo "${HOME}/.local/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
+      - name: Install MacOS dependencies (manim only)
+        if: matrix.os == 'macos-latest' && matrix.manim == 'manim'
+        run: brew install py3cairo
+      - name: Install MacOS dependencies
+        if: matrix.os == 'macos-latest'
+        run: brew install ffmpeg
+      - name: Install Ubuntu dependencies
+        if: matrix.os == 'ubuntu-latest'
+        run: sudo apt install libcairo2-dev libpango1.0-dev ffmpeg freeglut3-dev xvfb
+      - name: Install Windows dependencies
+        if: matrix.os == 'windows-latest'
+        run: choco install ffmpeg
+      - name: Install manim on MacOs
+        if: matrix.manim == 'manim' && matrix.os == 'macos-latest'
+        run: pip3 install --user manim
+      - name: Install manim on Ubuntu and Windows
+        if: matrix.manim == 'manim' && (matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest')
+        run: python -m pip install --user manim
+      - name: Install manimgl on MacOs
+        if: matrix.manim == 'manimgl' && matrix.os == 'macos-latest'
+        run: pip3 install --user manimgl
+      - name: Install manimgl on Ubuntu and Windows
+        if: matrix.manim == 'manimgl' && matrix.os != 'macos-latest'
+        run: python -m pip install --user manimgl
+      - name: Install manim-slides on MacOS
+        if: matrix.os == 'macos-latest'
+        run: pip3 install --user .
+      - name: Install manim-slides on Ubuntu
+        if: matrix.os == 'ubuntu-latest'
+        run: xvfb-run -a -s "-screen 0 1400x900x24" python -m pip install --user .
+      - name: Install manim-slides on Windows
+        if: matrix.os == 'windows-latest'
+        run: pip3 install -e .
+      - name: Build slides with manim
+        if: matrix.manim == 'manim'
+        run: python -m manim -ql example.py Example ThreeDExample
+      - name: Build slides with manimgl on Ubuntu
+        if: matrix.manim == 'manimgl' && matrix.os == 'ubuntu-latest'
+        run: xvfb-run -a -s "-screen 0 1400x900x24" manim-render -l example.py Example ThreeDExample
+      - name: Build slides with manimgl on MacOS or Windows
+        if: matrix.manim == 'manimgl' && (matrix.os == 'macos-latest' || matrix.os == 'windows-latest')
+        run: manimgl -l example.py Example ThreeDExample
+      - name: Test slides on Ubuntu
+        if: matrix.os == 'ubuntu-latest'
+        run: xvfb-run -a -s "-screen 0 1400x900x24" manim-slides Example ThreeDExample --skip-all
+      - name: Test slides on MacOS or Windows
+        if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest'
+        run: manim-slides Example ThreeDExample --skip-all
diff --git a/example.py b/example.py
index 2938047..f0e8d8e 100644
--- a/example.py
+++ b/example.py
@@ -1,6 +1,15 @@
-# If you want to use manimgl, uncomment change
-# manim to manimlib
-from manimlib import *
+import sys
+
+if "manim" in sys.modules:
+    from manim import *
+
+    MANIMGL = False
+elif "manimlib" in sys.modules:
+    from manimlib import *
+
+    MANIMGL = True
+else:
+    raise ImportError("This script must be run with either `manim` or `manimgl`")
 
 from manim_slides import Slide, ThreeDSlide
 
@@ -31,37 +40,88 @@ class Example(Slide):
         self.play(dot.animate.move_to(ORIGIN))
 
 
-class ThreeDExample(ThreeDSlide):
-    def construct(self):
-        axes = ThreeDAxes()
-        circle = Circle(radius=3, color=BLUE)
-        dot = Dot(color=RED)
+# For ThreeDExample, things are different
 
-        self.add(axes)
+if not MANIMGL:
 
-        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
+    class ThreeDExample(ThreeDSlide):
+        def construct(self):
+            axes = ThreeDAxes()
+            circle = Circle(radius=3, color=BLUE)
+            dot = Dot(color=RED)
 
-        self.play(GrowFromCenter(circle))
-        self.begin_ambient_camera_rotation(rate=75 * DEGREES / 4)
+            self.add(axes)
 
-        self.pause()
+            self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
 
-        self.start_loop()
-        self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
-        self.end_loop()
+            self.play(GrowFromCenter(circle))
+            self.begin_ambient_camera_rotation(rate=75 * DEGREES / 4)
 
-        self.stop_ambient_camera_rotation()
-        self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)
+            self.pause()
 
-        self.play(dot.animate.move_to(ORIGIN))
-        self.pause()
+            self.start_loop()
+            self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
+            self.end_loop()
 
-        self.play(dot.animate.move_to(RIGHT * 3))
-        self.pause()
+            self.stop_ambient_camera_rotation()
+            self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)
 
-        self.start_loop()
-        self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
-        self.end_loop()
+            self.play(dot.animate.move_to(ORIGIN))
+            self.pause()
 
-        # Each slide MUST end with an animation (a self.wait is considered an animation)
-        self.play(dot.animate.move_to(ORIGIN))
+            self.play(dot.animate.move_to(RIGHT * 3))
+            self.pause()
+
+            self.start_loop()
+            self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
+            self.end_loop()
+
+            # Each slide MUST end with an animation (a self.wait is considered an animation)
+            self.play(dot.animate.move_to(ORIGIN))
+
+else:
+    # WARNING: 3b1b's manim change how ThreeDScene work,
+    # this is why things have to be managed differently.
+    class ThreeDExample(Slide):
+        CONFIG = {
+            "camera_class": ThreeDCamera,
+        }
+
+        def construct(self):
+            axes = ThreeDAxes()
+            circle = Circle(radius=3, color=BLUE)
+            dot = Dot(color=RED)
+
+            self.add(axes)
+
+            frame = self.camera.frame
+            frame.set_euler_angles(
+                theta=30 * DEGREES,
+                phi=75 * DEGREES,
+                gamma=0,
+            )
+
+            self.play(GrowFromCenter(circle))
+            updater = lambda m, dt: m.increment_theta((75 * DEGREES / 4) * dt)
+            frame.add_updater(updater)
+
+            self.pause()
+
+            self.start_loop()
+            self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
+            self.end_loop()
+
+            frame.remove_updater(updater)
+            self.play(frame.animate.set_theta(30 * DEGREES))
+            self.play(dot.animate.move_to(ORIGIN))
+            self.pause()
+
+            self.play(dot.animate.move_to(RIGHT * 3))
+            self.pause()
+
+            self.start_loop()
+            self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
+            self.end_loop()
+
+            # Each slide MUST end with an animation (a self.wait is considered an animation)
+            self.play(dot.animate.move_to(ORIGIN))
diff --git a/manim_slides/__version__.py b/manim_slides/__version__.py
index 1e3bed4..3348d7f 100644
--- a/manim_slides/__version__.py
+++ b/manim_slides/__version__.py
@@ -1 +1 @@
-__version__ = "3.2.2"
+__version__ = "3.2.3"
diff --git a/manim_slides/present.py b/manim_slides/present.py
index 8190951..ac648dc 100644
--- a/manim_slides/present.py
+++ b/manim_slides/present.py
@@ -174,10 +174,18 @@ class Presentation:
 
 
 class Display:
-    def __init__(self, presentations, config, start_paused=False, fullscreen=False):
+    def __init__(
+        self,
+        presentations,
+        config,
+        start_paused=False,
+        fullscreen=False,
+        skip_all=False,
+    ):
         self.presentations = presentations
         self.start_paused = start_paused
         self.config = config
+        self.skip_all = skip_all
 
         self.state = State.PLAYING
         self.lastframe = None
@@ -206,7 +214,7 @@ class Display:
 
         scale = min(scale_height, scale_width)
 
-        return cv2.resize(frame, (int(scale * frame_height, scale * frame_width)))
+        return cv2.resize(frame, (int(scale * frame_height), int(scale * frame_width)))
 
     @property
     def current_presentation(self):
@@ -293,7 +301,9 @@ class Display:
         ):
             self.current_presentation.next()
             self.state = State.PLAYING
-        elif self.state == State.PLAYING and self.config.CONTINUE.match(key):
+        elif (
+            self.state == State.PLAYING and self.config.CONTINUE.match(key)
+        ) or self.skip_all:
             self.current_presentation.next()
         elif self.config.BACK.match(key):
             if self.current_presentation.current_slide_i == 0:
@@ -356,8 +366,15 @@ def _list_scenes(folder):
     is_flag=True,
     help="Show the next animation first frame as last frame (hack).",
 )
+@click.option(
+    "--skip-all",
+    is_flag=True,
+    help="Skip all slides, useful the test if slides are working.",
+)
 @click.help_option("-h", "--help")
-def present(scenes, config_path, folder, start_paused, fullscreen, last_frame_next):
+def present(
+    scenes, config_path, folder, start_paused, fullscreen, last_frame_next, skip_all
+):
     """Present the different scenes."""
 
     if len(scenes) == 0:
@@ -411,6 +428,10 @@ def present(scenes, config_path, folder, start_paused, fullscreen, last_frame_ne
         config = Config()
 
     display = Display(
-        presentations, config=config, start_paused=start_paused, fullscreen=fullscreen
+        presentations,
+        config=config,
+        start_paused=start_paused,
+        fullscreen=fullscreen,
+        skip_all=skip_all,
     )
     display.run()
diff --git a/setup.py b/setup.py
index 9000aab..0de4214 100644
--- a/setup.py
+++ b/setup.py
@@ -32,7 +32,7 @@ setuptools.setup(
         "numpy>=1.19.3",
         "pydantic>=1.9.1",
         "opencv-python>=4.6",
-        "tqdm",
+        "tqdm>=4.62.3",
     ],
     classifiers=[
         "Programming Language :: Python :: 3",