Real-Time JavaScript/TypeScript UI playground.
MIT License
Real-Time JavaScript/TypeScript UI playground.
Noxtron is a configurable web tool to explore, preview, and test JavaScript and TypeScript components as isolated sandboxes in realtime in browser. It is composed by two applications, a playground app with the interface to explore and control predefined sandboxes, and a sandbox app to execute the sandboxes source code.
A sandbox is a named code snippet which represents an independent and isolated functionality use case.
import
/** @jsx XXX */
can be used inline toNoxtron use case with plain JavaScript and React v17.
Using Node.js v16 LTS, in an empty folder:
node -v # v16
# Create the following file structure
mkdir -p src
touch src/playground.html
touch src/playground.js
touch src/sandbox.html
touch src/sandbox.js
touch webpack.config.js
# Create package.json
npm init -y
# Install noxtron
npm i [email protected]
# Install external libraries for the sandboxes source code.
# They are not required for Noxtron, only based on user configuration.
npm i react@17 react-dom@17
NPM scripts can be used to setup the application workflow tasks. To setup, bundle, and test the applications files and modules, webpack can be used.
npm i -D webpack@5 \
webpack-cli@4 \
webpack-dev-server@4 \
html-webpack-plugin@5
Configure Webpack script.
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UMD_PATH = path.join(__dirname, 'node_modules/noxtron/build/umd');
const SRC_PATH = path.join(__dirname, 'src');
const BUILD_PATH = path.join(__dirname, 'build');
module.exports = {
mode: 'development',
devtool: false,
entry: {
playground: path.join(SRC_PATH, 'playground.js'),
sandbox: path.join(SRC_PATH, 'sandbox.js')
},
output: {
path: BUILD_PATH,
filename: '[name].js',
clean: true
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(SRC_PATH, 'playground.html'),
filename: path.join(BUILD_PATH, 'index.html'),
chunks: ['playground']
}),
new HtmlWebpackPlugin({
template: path.join(SRC_PATH, 'sandbox.html'),
filename: path.join(BUILD_PATH, 'sandbox/index.html'),
chunks: ['sandbox']
})
],
devServer: {
static: [
{
directory: UMD_PATH,
publicPath: '/noxtron/',
watch: true
},
{
directory: BUILD_PATH,
watch: true
}
],
allowedHosts: 'all',
compress: true,
host: '127.0.0.1',
port: 4000,
open: '/'
}
};
The folder ./build/
will have the final public applications.
The Noxtron UMD files located at /node_modules/noxtron/build/umd/
will be copied
to /build/noxtron/
so they are accessible publicly.
Then add the following script to setup and run the application.
// package.json
{
// ...
"scripts": {
"dev": "webpack serve"
}
}
The playground application shows the explorer and controls of the sandboxes configured. It is required to add a HTML element to render the interface and include the Noxtron playground app UMD file.
<!-- src/playground.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Noxtron Playground</title>
</head>
<body>
<!-- HTML element to render the interface -->
<div id="root"></div>
<!-- Noxtron playground app UMD entry file -->
<script src="/noxtron/playground.js"></script>
</body>
</html>
// src/playground.js
window.noxtron.setupPlayground(() => ({
// Root HTML element to render playground app.
element: document.querySelector('#root'),
// The URL path to the playground app.
basePath: '/',
// The URL path to the Noxtron asset files.
// In this case, the "node_modules/noxtron/build/umd/" files are copied to the
// server URL public folder at "/noxtron/".
assetsPath: '/noxtron/',
// The playground app HTML URL.
// In this case, it is "/" which will render to "/index.html"
// to have a clean URL.
playgroundPath: '/',
// The sandbox app HTML URL.
// In this case, it is "/sandbox/" which will render to "/sandbox/index.html"
// to have a clean URL.
sandboxPath: '/sandbox/',
// Sandboxes source code language. "javascript" | "typescript".
codeLanguage: 'javascript',
// Playground app title for different viewport widths.
title: {
small: 'MyOrg',
medium: 'My Organization'
},
// Get the sandboxes list. Since this list contains every sandbox source code,
// it may get big in filesize. It should be lazy loaded if possible.
// They can use only packages provided by the sandbox app.
// In this case, "react" and "react-dom" are available to use.
getSandboxes: () => [
{
name: 'MyComponent',
children: [
{
name: 'sandbox1',
code: `import React from 'react';
import { render } from 'react-dom';
const Sandbox = () => <h1 style={{ color: 'yellow' }}>My Sandbox 1</h1>;
render(<Sandbox />, document.querySelector('#root'));
`
},
{
name: 'sandbox2',
code: `import React from 'react';
import { render } from 'react-dom';
const Sandbox = () => <h1 style={{ color: 'magenta' }}>My Sandbox 2</h1>;
render(<Sandbox />, document.querySelector('#root'));
`
}
// ...
]
}
]
}));
The sandbox app executes the actual sandboxes source code and custom source code. It is required to include the Noxtron sandbox app UMD file and the user setup, in this case, in a different JavaScript file.
<!-- src/sandbox.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Noxtron Sandbox</title>
</head>
<body>
<!-- Since the sandboxes are going to use React, create a root element. -->
<div id="root"></div>
<!-- Noxtron sandbox app UMD entry file -->
<script src="/noxtron/sandbox.js"></script>
</body>
</html>
Only the dependencies provided to the sandbox setup can be used in the sandboxes source code with ES modules.
// src/sandbox.js
import React from 'react';
import ReactDOM from 'react-dom';
window.noxtron.setupSandbox(() => ({
dependencies: [
{ name: 'react', pkg: React },
{ name: 'react-dom', pkg: ReactDOM }
]
}));
To run the application:
npm run dev
Finally, open it at http://127.0.0.1:4000
.
For more, check out the project examples.
Noxtron's logo is a photo of a bird named Ninfa Coronada endemic from Colombia. Source: birdsofcolombia.com.