A library-agnostic framework for building concise, testable, and universal Node.js web apps.
Switch out underlying libraries without changing application code.
Uses the definite pattern to keep code clean, testable, and extensible.
npm install -g paradiso
Paradiso is just a custom definite class builder. Please read more about definite if you haven't.
Paradiso classes have the following definite
instances available:
First, let's create a very simple project with the following structure:
app/
components/
- home.js
init/
- app.js
- client.js
- server.js
- styles.scss
(Protip: Feel free to organize your files how you like. Paradiso is unopinionated.)
app/init/app.js
:
import paradiso from "paradiso"
class App {
client() {
return this.paradiso.client({
router: this.router(),
type: "mithril"
})
}
router() {
return this.paradiso.router({
"/": "../components/home"
})
}
server() {
return this.paradiso.server({
port: 9000,
router: this.router(),
static: "public",
type: "express"
})
}
}
export default paradiso(App)
app/init/client.js
:
import app from "./app"
export default app().client()
app/init/server.js
:
import app from "./app"
export default app().server()
components/home.js
:
import paradiso from "paradiso"
class Home {
then() { return "hello!" }
}
export default paradiso(Home)
Use the diso
command to run your initialization classes:
diso init/client
(Protip: diso
is just an alias for the def
command)
Start the web server:
diso init/server
Now you have a functioning Paradiso project up and running at 127.0.0.1:9000.
This project is available in the getting-started branch of the example repo.
Let's build a more complex HTML page with content:
lib/component.js
:
import paradiso from "paradiso"
export default paradiso({
// Autoload dependencies
//
autoload: `${__dirname}/../components`
})
lib/view.js
:
import component from "./component"
import sugartags from "./def-sugar"
export default component({
// Views should never hold state
//
key: null,
// Sugartags for templating
//
mixins: [ sugartags ]
})
components/layout/layout.view.js
:
import view from "../lib/view"
class LayoutView {
then() {
return HTML [
HEAD(this.options.title)
BODY(this.options.content)
]
}
})
export default view(LayoutView)
components/home/home.js
:
import component from "../lib/component"
class Home {
then() {
let title = `home`
let content = [
H1(this.title),
P(`hello`)
]
if this.options.server
return this.components.layout.view({ content, title })
else
return content
}
}
export default component(Home)