diff --git a/.env b/.env new file mode 100644 index 00000000..fefc515a --- /dev/null +++ b/.env @@ -0,0 +1 @@ +NULLSTACK_SERVER_PORT=5000 \ No newline at end of file diff --git a/.github/workflows/ssg-build.yml b/.github/workflows/ssg-build.yml new file mode 100644 index 00000000..f32d4a95 --- /dev/null +++ b/.github/workflows/ssg-build.yml @@ -0,0 +1,42 @@ +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: SSG Build to Deploy + +on: + push: + branches: [ master ] + workflow_dispatch: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + # cache the dependencies from any node_modules directory + - name: Cache dependencies + uses: actions/cache@v2 + with: + path: | + **/node_modules + **/package-lock.json + **/.production + key: node_modules-${{ hashFiles('**/package.json') }} + + - name: Install deps + run: npm install + + - name: Build + run: npx nullstack build --mode=ssg --output=docs + + - name: Send to Github + run: | + git branch gh-pages -f + git checkout gh-pages + touch ./docs/.nojekyll + git add docs -f + git config --global user.name "NullstackDeployer" + git config --global user.email "nullstack@deployer.ci" + git commit -m ":rocket: New SSG Build" + git push -u origin gh-pages -f \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9792703c..81cf24c6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ node_modules package-lock.json yarn.lock .development -.production \ No newline at end of file +.production +public/pt-BR.json +public/en-US.json +docs diff --git a/README.br.md b/README.br.md new file mode 100644 index 00000000..2ff90cac --- /dev/null +++ b/README.br.md @@ -0,0 +1,21 @@ +# Documentação do Nullstack + +Nullstack + +## Como executar este projeto + +Instale as dependências: + +`npm install` + +Rode a aplicação no modo de desenvolvimento: + +`npm start` + +Abra [http://localhost:5000](http://localhost:5000) para vê-lo no navegador. + +## Aprenda mais sobre o Nullstack + +[Leia a documentação](https://nullstack.app/pt-br/comecando) + + Read in English \ No newline at end of file diff --git a/README.md b/README.md index f6b6edc1..196e83fb 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,6 @@ Open [http://localhost:5000](http://localhost:5000) to view it in the browser. ## Learn more about Nullstack -[Read the documentation](https://nullstack.app/documentation) \ No newline at end of file +[Read the documentation](https://nullstack.app/getting-started) + + Leia em Português \ No newline at end of file diff --git a/client.js b/client.js new file mode 100644 index 00000000..e251a2a3 --- /dev/null +++ b/client.js @@ -0,0 +1,6 @@ +import Nullstack from "nullstack"; +import Application from "./src/Application"; + +const context = Nullstack.start(Application); + +export default context \ No newline at end of file diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index fd10b8e2..00000000 --- a/docs/404.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Page Not Found - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Page Not Found

- - - \ No newline at end of file diff --git a/docs/404/index.html b/docs/404/index.html deleted file mode 100644 index fd10b8e2..00000000 --- a/docs/404/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Page Not Found - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Page Not Found

- - - \ No newline at end of file diff --git a/docs/404/index.json b/docs/404/index.json deleted file mode 100644 index 3758ada4..00000000 --- a/docs/404/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Page Not Found","html":"

Perhaps you want to learn about how to make a 404 page with Nullstack?

\n

If you are looking for something else, you should read the documentation.

\n","description":"Sorry, this is not the page you are looking for.","status":404},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":404,"title":"Page Not Found - Nullstack","description":"Sorry, this is not the page you are looking for."}} \ No newline at end of file diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index e242231c..00000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -nullstack.app \ No newline at end of file diff --git a/docs/about.html b/docs/about.html deleted file mode 100644 index eaf89507..00000000 --- a/docs/about.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - Why Nullstack Exists - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Why Nullstack Exists

The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application.

-

It was created keeping in mind programmers used to developing entire systems alone, but it is easily scalable to small or even big teams, as long as each programmer knows the flow of the feature they are to develop.

-

The Stack

With the stack of technologies used in the web nowadays, the most common flow is something like this:

-
    -
  • Front-end uses a reducer over a context that calls a fetcher;
  • -
  • This fetcher brings generic information over a RESTful API;
  • -
  • The RESTful API calls a server route, which calls a controller, which takes the information of a model and resolves it into a serializer;
  • -
  • If you need more than one resource, this process should be repeated until all resources are fetched;
  • -
  • After all the data has been fetched, only then should the front-end be able to use it;
  • -
  • Reason about how to deal with server-side render and hydration of the steps above;
  • -
-

Note that all you wanted was to show something from the database into a view. With Nullstack, that’s all you need to concern yourself with. Everything else is “glue code” and the framework should take care of it for you.

-

Feature-driven

If you’re used to working on more than one project at a time or even if you just happen to have to give sporadic maintenance to a lot of your old projects, you might have stumbled upon this scenario: you don’t remember exactly where in your code is the logic you’re trying to fix or improve.

-

You might have a hook whose dependencies are local variables initialized with a redux state, which was stored at some point by an action declared somewhere in your source tree and called in who knows where.

-

If everything pertaining to a single feature were to be in the same file, maybe you wouldn’t need to reverse engineer your own code every time you need to update or fix something.

-

Putting everything in a single file may sound messy at a glance, but remember that you are the one who decides the granularity of this division.

-

A "feature" might be an entire register form or something as small as a button that does some verifications before letting you submit that form. It’s entirely up to you, and since each component is as complete as an entire feature, you could call this button or even the entire form on other pages in your application. This leads us to True Componentization and Code Reusability.

-

Componentization and Code Reusability

Components in Nullstack are self-sufficient.

-

Most frameworks are specialized in a single layer, meaning that any component will be only as complete as its framework. When exporting a Nullstack component, all the code needed to run the feature is going to be together, without the need of allocating the other layers separately.

-

As a side effect, entire applications can be used as components, and mounted in other applications as engines.

-

Why object-oriented instead of functional

At first glance, classes may look more verbose than the trendy functional components. -This section will explain the reasons that lead us to favor classes in the development of Nullstack.

-

The reasons are actually connected to some core principles of Nullstack, being:

-

Everything as Vanilla as Possible

We didn’t want to introduce a “Nullstack way” of doing things and wanted it to be accessible to anyone with some Javascript knowledge.

-

That being said, the first big problem was to address state management in a vanilla Javascript way. Supporting functional components would require a solution similar to the hooks of React.js that would be considered a mannerism of the framework.

-

Since we opted out of immutability as a framework constraint, we are allowed to use the native way of setting simple variables. This removes the complexity of state management that created the need of third-party state management libraries in the first place.

-

No Glue Code or “Batteries Included”

Nullstack borrows the concept of “battery-included” from Ember.js, but allows you to change batteries. Everything you need to make an application should be part of the framework, and still be flexible.

-

A framework should do the heavy lifting and a programmer should focus on his own application. -For this reason, all you have to do is to declare your classes and let Nullstack instantiate them for you. That way, we removed the most painful aspect of dealing with classes while maintaining all of the advantages of them.

-

Having a safe escape route

Object-oriented versus functional is not a new topic, and lately the former seems to be bullied out of most frameworks, leaving no place for developers that enjoy this pattern.

-

Admittedly classes took too long to be standardized into Javascript and the delay might have caused some traumatic bad implementations along the way.

-

While object-oriented programming might not be the best solution for every problem, Nullstack allows you to import functions freely and use them in the moments when they should be the weapon of choice.

-

Why dependency injection instead of modularity

Nullstack context uses the dependency injection pattern, which means that everything you need can be requested from the framework at the signature level of the function.

-

The context is a horizontally scoped object that is injected in all of your function calls. The non-hierarchical nature of this pattern allows you to easily move around your component's logic as your application grows, while still avoiding problems like props drilling or filling your view layer with store declarations.

-

This has two major advantages:

-
    -
  • You see the dependencies of your code at a function level instead of having them all imported on top of the file.

  • -
  • The framework is able to give you the most precise information about the specific environment for that function call.

  • -
-

Developer Happiness

The generated application is enough to have a PWA without thinking about boilerplates, but you are completely free to override the default behavior of each moving piece.

-

A borrowed concept from Ruby is developer happiness. Nullstack aims to ease the developer’s life by simplifying everything possible, but without hiding things from you.

-

The first developers we wanted to make happy are ourselves. We made Nullstack because we had fun in the process. It started as a simple prototype on top of React.js and we got carried away, each time making it more enjoyable for us until it became its own thing.

-

We hope you enjoy using Nullstack as much as we do because that's what keeps this project going forward.

-
- - - \ No newline at end of file diff --git a/docs/about/index.html b/docs/about/index.html deleted file mode 100644 index eaf89507..00000000 --- a/docs/about/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - Why Nullstack Exists - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Why Nullstack Exists

The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application.

-

It was created keeping in mind programmers used to developing entire systems alone, but it is easily scalable to small or even big teams, as long as each programmer knows the flow of the feature they are to develop.

-

The Stack

With the stack of technologies used in the web nowadays, the most common flow is something like this:

-
    -
  • Front-end uses a reducer over a context that calls a fetcher;
  • -
  • This fetcher brings generic information over a RESTful API;
  • -
  • The RESTful API calls a server route, which calls a controller, which takes the information of a model and resolves it into a serializer;
  • -
  • If you need more than one resource, this process should be repeated until all resources are fetched;
  • -
  • After all the data has been fetched, only then should the front-end be able to use it;
  • -
  • Reason about how to deal with server-side render and hydration of the steps above;
  • -
-

Note that all you wanted was to show something from the database into a view. With Nullstack, that’s all you need to concern yourself with. Everything else is “glue code” and the framework should take care of it for you.

-

Feature-driven

If you’re used to working on more than one project at a time or even if you just happen to have to give sporadic maintenance to a lot of your old projects, you might have stumbled upon this scenario: you don’t remember exactly where in your code is the logic you’re trying to fix or improve.

-

You might have a hook whose dependencies are local variables initialized with a redux state, which was stored at some point by an action declared somewhere in your source tree and called in who knows where.

-

If everything pertaining to a single feature were to be in the same file, maybe you wouldn’t need to reverse engineer your own code every time you need to update or fix something.

-

Putting everything in a single file may sound messy at a glance, but remember that you are the one who decides the granularity of this division.

-

A "feature" might be an entire register form or something as small as a button that does some verifications before letting you submit that form. It’s entirely up to you, and since each component is as complete as an entire feature, you could call this button or even the entire form on other pages in your application. This leads us to True Componentization and Code Reusability.

-

Componentization and Code Reusability

Components in Nullstack are self-sufficient.

-

Most frameworks are specialized in a single layer, meaning that any component will be only as complete as its framework. When exporting a Nullstack component, all the code needed to run the feature is going to be together, without the need of allocating the other layers separately.

-

As a side effect, entire applications can be used as components, and mounted in other applications as engines.

-

Why object-oriented instead of functional

At first glance, classes may look more verbose than the trendy functional components. -This section will explain the reasons that lead us to favor classes in the development of Nullstack.

-

The reasons are actually connected to some core principles of Nullstack, being:

-

Everything as Vanilla as Possible

We didn’t want to introduce a “Nullstack way” of doing things and wanted it to be accessible to anyone with some Javascript knowledge.

-

That being said, the first big problem was to address state management in a vanilla Javascript way. Supporting functional components would require a solution similar to the hooks of React.js that would be considered a mannerism of the framework.

-

Since we opted out of immutability as a framework constraint, we are allowed to use the native way of setting simple variables. This removes the complexity of state management that created the need of third-party state management libraries in the first place.

-

No Glue Code or “Batteries Included”

Nullstack borrows the concept of “battery-included” from Ember.js, but allows you to change batteries. Everything you need to make an application should be part of the framework, and still be flexible.

-

A framework should do the heavy lifting and a programmer should focus on his own application. -For this reason, all you have to do is to declare your classes and let Nullstack instantiate them for you. That way, we removed the most painful aspect of dealing with classes while maintaining all of the advantages of them.

-

Having a safe escape route

Object-oriented versus functional is not a new topic, and lately the former seems to be bullied out of most frameworks, leaving no place for developers that enjoy this pattern.

-

Admittedly classes took too long to be standardized into Javascript and the delay might have caused some traumatic bad implementations along the way.

-

While object-oriented programming might not be the best solution for every problem, Nullstack allows you to import functions freely and use them in the moments when they should be the weapon of choice.

-

Why dependency injection instead of modularity

Nullstack context uses the dependency injection pattern, which means that everything you need can be requested from the framework at the signature level of the function.

-

The context is a horizontally scoped object that is injected in all of your function calls. The non-hierarchical nature of this pattern allows you to easily move around your component's logic as your application grows, while still avoiding problems like props drilling or filling your view layer with store declarations.

-

This has two major advantages:

-
    -
  • You see the dependencies of your code at a function level instead of having them all imported on top of the file.

  • -
  • The framework is able to give you the most precise information about the specific environment for that function call.

  • -
-

Developer Happiness

The generated application is enough to have a PWA without thinking about boilerplates, but you are completely free to override the default behavior of each moving piece.

-

A borrowed concept from Ruby is developer happiness. Nullstack aims to ease the developer’s life by simplifying everything possible, but without hiding things from you.

-

The first developers we wanted to make happy are ourselves. We made Nullstack because we had fun in the process. It started as a simple prototype on top of React.js and we got carried away, each time making it more enjoyable for us until it became its own thing.

-

We hope you enjoy using Nullstack as much as we do because that's what keeps this project going forward.

-
- - - \ No newline at end of file diff --git a/docs/about/index.json b/docs/about/index.json deleted file mode 100644 index f054e428..00000000 --- a/docs/about/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Why Nullstack Exists","html":"

The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application.

\n

It was created keeping in mind programmers used to developing entire systems alone, but it is easily scalable to small or even big teams, as long as each programmer knows the flow of the feature they are to develop.

\n

The Stack

With the stack of technologies used in the web nowadays, the most common flow is something like this:

\n\n

Note that all you wanted was to show something from the database into a view. With Nullstack, that’s all you need to concern yourself with. Everything else is “glue code” and the framework should take care of it for you.

\n

Feature-driven

If you’re used to working on more than one project at a time or even if you just happen to have to give sporadic maintenance to a lot of your old projects, you might have stumbled upon this scenario: you don’t remember exactly where in your code is the logic you’re trying to fix or improve.

\n

You might have a hook whose dependencies are local variables initialized with a redux state, which was stored at some point by an action declared somewhere in your source tree and called in who knows where.

\n

If everything pertaining to a single feature were to be in the same file, maybe you wouldn’t need to reverse engineer your own code every time you need to update or fix something.

\n

Putting everything in a single file may sound messy at a glance, but remember that you are the one who decides the granularity of this division.

\n

A "feature" might be an entire register form or something as small as a button that does some verifications before letting you submit that form. It’s entirely up to you, and since each component is as complete as an entire feature, you could call this button or even the entire form on other pages in your application. This leads us to True Componentization and Code Reusability.

\n

Componentization and Code Reusability

Components in Nullstack are self-sufficient.

\n

Most frameworks are specialized in a single layer, meaning that any component will be only as complete as its framework. When exporting a Nullstack component, all the code needed to run the feature is going to be together, without the need of allocating the other layers separately.

\n

As a side effect, entire applications can be used as components, and mounted in other applications as engines.

\n

Why object-oriented instead of functional

At first glance, classes may look more verbose than the trendy functional components.\nThis section will explain the reasons that lead us to favor classes in the development of Nullstack.

\n

The reasons are actually connected to some core principles of Nullstack, being:

\n

Everything as Vanilla as Possible

We didn’t want to introduce a “Nullstack way” of doing things and wanted it to be accessible to anyone with some Javascript knowledge.

\n

That being said, the first big problem was to address state management in a vanilla Javascript way. Supporting functional components would require a solution similar to the hooks of React.js that would be considered a mannerism of the framework.

\n

Since we opted out of immutability as a framework constraint, we are allowed to use the native way of setting simple variables. This removes the complexity of state management that created the need of third-party state management libraries in the first place.

\n

No Glue Code or “Batteries Included”

Nullstack borrows the concept of “battery-included” from Ember.js, but allows you to change batteries. Everything you need to make an application should be part of the framework, and still be flexible.

\n

A framework should do the heavy lifting and a programmer should focus on his own application.\nFor this reason, all you have to do is to declare your classes and let Nullstack instantiate them for you. That way, we removed the most painful aspect of dealing with classes while maintaining all of the advantages of them.

\n

Having a safe escape route

Object-oriented versus functional is not a new topic, and lately the former seems to be bullied out of most frameworks, leaving no place for developers that enjoy this pattern.

\n

Admittedly classes took too long to be standardized into Javascript and the delay might have caused some traumatic bad implementations along the way.

\n

While object-oriented programming might not be the best solution for every problem, Nullstack allows you to import functions freely and use them in the moments when they should be the weapon of choice.

\n

Why dependency injection instead of modularity

Nullstack context uses the dependency injection pattern, which means that everything you need can be requested from the framework at the signature level of the function.

\n

The context is a horizontally scoped object that is injected in all of your function calls. The non-hierarchical nature of this pattern allows you to easily move around your component's logic as your application grows, while still avoiding problems like props drilling or filling your view layer with store declarations.

\n

This has two major advantages:

\n\n

Developer Happiness

The generated application is enough to have a PWA without thinking about boilerplates, but you are completely free to override the default behavior of each moving piece.

\n

A borrowed concept from Ruby is developer happiness. Nullstack aims to ease the developer’s life by simplifying everything possible, but without hiding things from you.

\n

The first developers we wanted to make happy are ourselves. We made Nullstack because we had fun in the process. It started as a simple prototype on top of React.js and we got carried away, each time making it more enjoyable for us until it became its own thing.

\n

We hope you enjoy using Nullstack as much as we do because that's what keeps this project going forward.

\n","description":"The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Why Nullstack Exists - Nullstack","description":"The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application"}} \ No newline at end of file diff --git a/docs/application-startup.html b/docs/application-startup.html deleted file mode 100644 index fb40a902..00000000 --- a/docs/application-startup.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - Application Startup - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Application Startup

The index.js file at your application root is responsible for starting your application.

-

When you run the application with npm start or node .production/server.js the index will call the start function in your src/Application.js.

-

The start function will run only once when your application is booted and is a good place for setting up your server context.

-
import Nullstack from 'nullstack';
-import database from './database';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.database = database;
-  }
-
-}
-
-export default Application;
-
-

Dependency startup pattern

A nice pattern to work with dependencies that require startup time configurations is to define a start function in the dependency and call it in the Application start function passing the server context.

-
import Nullstack from 'nullstack';
-import Dependency from './Dependency';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    Dependency.start(context);
-  }
-
-}
-
-export default Application;
-
-
-

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

-
-

Next step

⚔ Learn about the context data.

-
- - - \ No newline at end of file diff --git a/docs/application-startup/index.html b/docs/application-startup/index.html deleted file mode 100644 index fb40a902..00000000 --- a/docs/application-startup/index.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - Application Startup - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Application Startup

The index.js file at your application root is responsible for starting your application.

-

When you run the application with npm start or node .production/server.js the index will call the start function in your src/Application.js.

-

The start function will run only once when your application is booted and is a good place for setting up your server context.

-
import Nullstack from 'nullstack';
-import database from './database';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.database = database;
-  }
-
-}
-
-export default Application;
-
-

Dependency startup pattern

A nice pattern to work with dependencies that require startup time configurations is to define a start function in the dependency and call it in the Application start function passing the server context.

-
import Nullstack from 'nullstack';
-import Dependency from './Dependency';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    Dependency.start(context);
-  }
-
-}
-
-export default Application;
-
-
-

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

-
-

Next step

⚔ Learn about the context data.

-
- - - \ No newline at end of file diff --git a/docs/application-startup/index.json b/docs/application-startup/index.json deleted file mode 100644 index 90229f04..00000000 --- a/docs/application-startup/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Application Startup","html":"

The index.js file at your application root is responsible for starting your application.

\n

When you run the application with npm start or node .production/server.js the index will call the start function in your src/Application.js.

\n

The start function will run only once when your application is booted and is a good place for setting up your server context.

\n
import Nullstack from 'nullstack';\nimport database from './database';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    context.database = database;\n  }\n\n}\n\nexport default Application;\n
\n

Dependency startup pattern

A nice pattern to work with dependencies that require startup time configurations is to define a start function in the dependency and call it in the Application start function passing the server context.

\n
import Nullstack from 'nullstack';\nimport Dependency from './Dependency';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    Dependency.start(context);\n  }\n\n}\n\nexport default Application;\n
\n
\n

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

\n
\n

Next step

⚔ Learn about the context data.

\n","description":"The start function will run only once when your application is booted and is a good place for setting up your server context"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Application Startup - Nullstack","description":"The start function will run only once when your application is booted and is a good place for setting up your server context"}} \ No newline at end of file diff --git a/docs/client-9cdb5778f42a90a83e1427c9316c97d3.css b/docs/client-9cdb5778f42a90a83e1427c9316c97d3.css deleted file mode 100644 index 2efe3b0d..00000000 --- a/docs/client-9cdb5778f42a90a83e1427c9316c97d3.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{margin:0.67em 0}a{background-color:transparent}b,strong{font-weight:bolder}img{border-style:none}button{line-height:1.15;margin:0}button{overflow:visible}button{text-transform:none}button,[type="button"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring{outline:1px dotted ButtonText}blockquote,h1,h2,h3,h4,p,pre{margin:0}button{background-color:transparent;background-image:none;padding:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}ul{list-style:none;margin:0;padding:0}html{line-height:1.2}*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e2e8f0}img{border-style:solid}button,[role="button"]{cursor:pointer}a{color:inherit;text-decoration:inherit}button{padding:0;line-height:inherit;color:inherit}img,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}body *{box-sizing:border-box}:root{--spacer: 0.25rem}@media (min-width: 0px){.m1y{margin-top:calc(var(--spacer) * 1)}.m1b,.m1y{margin-bottom:calc(var(--spacer) * 1)}.m2x{margin-left:calc(var(--spacer) * 2)}.m2x{margin-right:calc(var(--spacer) * 2)}.m2t{margin-top:calc(var(--spacer) * 2)}.m2b{margin-bottom:calc(var(--spacer) * 2)}.m3y{margin-top:calc(var(--spacer) * 3)}.m3b,.m3y{margin-bottom:calc(var(--spacer) * 3)}.m4t,.m4y{margin-top:calc(var(--spacer) * 4)}.m4b,.m4y{margin-bottom:calc(var(--spacer) * 4)}.m6y{margin-top:calc(var(--spacer) * 6)}.m6b,.m6y{margin-bottom:calc(var(--spacer) * 6)}.m8t{margin-top:calc(var(--spacer) * 8)}.m8b{margin-bottom:calc(var(--spacer) * 8)}.m10y{margin-top:calc(var(--spacer) * 10)}.m10b,.m10y{margin-bottom:calc(var(--spacer) * 10)}.m12b{margin-bottom:calc(var(--spacer) * 12)}.m14t{margin-top:calc(var(--spacer) * 14)}.m20t{margin-top:calc(var(--spacer) * 20)}.p1{padding:calc(var(--spacer) * 1)}.p1b{padding-bottom:calc(var(--spacer) * 1)}.p2{padding:calc(var(--spacer) * 2)}.p2t,.p2y{padding-top:calc(var(--spacer) * 2)}.p2b,.p2y{padding-bottom:calc(var(--spacer) * 2)}.p3y{padding-top:calc(var(--spacer) * 3)}.p3y{padding-bottom:calc(var(--spacer) * 3)}.p4{padding:calc(var(--spacer) * 4)}.p4x{padding-left:calc(var(--spacer) * 4)}.p4x{padding-right:calc(var(--spacer) * 4)}.p4t{padding-top:calc(var(--spacer) * 4)}.p5y{padding-top:calc(var(--spacer) * 5)}.p5y{padding-bottom:calc(var(--spacer) * 5)}.p8y{padding-top:calc(var(--spacer) * 8)}.p8y{padding-bottom:calc(var(--spacer) * 8)}.p10t,.p10y{padding-top:calc(var(--spacer) * 10)}.p10y{padding-bottom:calc(var(--spacer) * 10)}.p20y{padding-top:calc(var(--spacer) * 20)}.p20y{padding-bottom:calc(var(--spacer) * 20)}}@media (max-width: 768px){.sm\-m1y{margin-top:calc(var(--spacer) * 1)}.sm\-m1y{margin-bottom:calc(var(--spacer) * 1)}.sm\-m3t{margin-top:calc(var(--spacer) * 3)}.sm\-m10t{margin-top:calc(var(--spacer) * 10)}.sm\-p2l,.sm\-p2x{padding-left:calc(var(--spacer) * 2)}.sm\-p2x{padding-right:calc(var(--spacer) * 2)}.sm\-p4{padding:calc(var(--spacer) * 4)}.sm\-p4x{padding-left:calc(var(--spacer) * 4)}.sm\-p4x{padding-right:calc(var(--spacer) * 4)}.sm\-p4t{padding-top:calc(var(--spacer) * 4)}.sm\-p10t,.sm\-p10y{padding-top:calc(var(--spacer) * 10)}.sm\-p10y{padding-bottom:calc(var(--spacer) * 10)}}@media (max-width: 992px){.md\-p2x{padding-left:calc(var(--spacer) * 2)}.md\-p2x{padding-right:calc(var(--spacer) * 2)}}@media (min-width: 768px){.md\+m2x{margin-left:calc(var(--spacer) * 2)}.md\+m2x{margin-right:calc(var(--spacer) * 2)}.md\+m20t{margin-top:calc(var(--spacer) * 20)}.md\+p3l{padding-left:calc(var(--spacer) * 3)}.md\+p10l{padding-left:calc(var(--spacer) * 10)}.md\+p10y{padding-top:calc(var(--spacer) * 10)}.md\+p10b,.md\+p10y{padding-bottom:calc(var(--spacer) * 10)}.md\+p20t,.md\+p20y{padding-top:calc(var(--spacer) * 20)}.md\+p20y{padding-bottom:calc(var(--spacer) * 20)}}@media (max-width: 1200px){.lg\-p2x{padding-left:calc(var(--spacer) * 2)}.lg\-p2x{padding-right:calc(var(--spacer) * 2)}}@media (min-width: 0px){.pftl{position:fixed;left:0;top:0}.pabl{position:absolute;left:0;bottom:0}.prtl{position:relative;left:0;top:0}}:root{--box-shadow: 2px}@media (min-width: 0px){.bs2{box-shadow:0 0px calc(2 * var(--box-shadow)) 0 rgba(0,0,0,0.2)}}@media (min-width: 0px){.z24{z-index:2400}}@media (max-width: 768px){.sm\-off{display:none !important}}@media (min-width: 768px){.md\+off{display:none !important}}.x{width:100%}@media (min-width: 992px){.x{max-width:960px;margin-left:auto;margin-right:auto}}@media (min-width: 1200px){.x{max-width:1140px;margin-left:auto;margin-right:auto}}@media (min-width: 0px){.xl{display:flex;flex-wrap:wrap;justify-content:flex-start;text-align:left}.xx{display:flex;flex-wrap:wrap;justify-content:center;text-align:center}.xr{display:flex;flex-wrap:wrap;justify-content:flex-end;text-align:right}.xsb{display:flex;flex-wrap:wrap;justify-content:space-between}}@media (min-width: 0px){.yy{display:flex;flex-wrap:wrap;align-content:center}}@media (max-width: 768px){.sm\-xr{display:flex;flex-wrap:wrap;justify-content:flex-end;text-align:right}.sm\-xsb{display:flex;flex-wrap:wrap;justify-content:space-between}}:root{--x-columns: 12;--y-columns: 12;--y-height: 100%;--x-width: 100%}@media (min-width: 0px){.xvw{--x-width: 100vw}.x8{width:calc((var(--x-width) / var(--x-columns)) * 8) !important}.x12{width:calc((var(--x-width) / var(--x-columns)) * 12) !important}.yvh{--y-height: 100vh}.y12{height:calc((var(--y-height) / var(--y-columns)) * 12) !important}}@media (max-width: 768px){.sm\-x4{width:calc((var(--x-width) / var(--x-columns)) * 4) !important}.sm\-x6{width:calc((var(--x-width) / var(--x-columns)) * 6) !important}.sm\-x12{width:calc((var(--x-width) / var(--x-columns)) * 12) !important}}@media (max-width: 992px){.md\-x12{width:calc((var(--x-width) / var(--x-columns)) * 12) !important}}@media (min-width: 768px){.md\+x4{width:calc((var(--x-width) / var(--x-columns)) * 4) !important}.md\+x6{width:calc((var(--x-width) / var(--x-columns)) * 6) !important}.md\+x10{width:calc((var(--x-width) / var(--x-columns)) * 10) !important}}@media (max-width: 1200px){.lg\-x12z{max-width:calc((var(--x-width) / var(--x-columns)) * 12) !important}}@media (min-width: 992px){.lg\+x6{width:calc((var(--x-width) / var(--x-columns)) * 6) !important}}:root{--font-size: 0.25rem}@media (min-width: 0px){.fs4{font-size:calc(4 * var(--font-size))}.fs6{font-size:calc(6 * var(--font-size))}}@media (max-width: 768px){.sm\-fs6{font-size:calc(6 * var(--font-size))}.sm\-fs8{font-size:calc(8 * var(--font-size))}}@media (min-width: 768px){.md\+fs8{font-size:calc(8 * var(--font-size))}.md\+fs12{font-size:calc(12 * var(--font-size))}}:root{--primary-font-family: 'Arial';--secondary-font-family: 'Tahoma';--tertiary-font-family: 'Tahoma'}@media (min-width: 0px){.ff2{font-family:var(--secondary-font-family)}}@media (min-width: 0px){.fw3{font-weight:300}}:root{--line-height: 0.1}@media (min-width: 0px){.lh12{line-height:calc(12 * var(--line-height))}.lh16{line-height:calc(16 * var(--line-height))}}:root{--primary-color: #d22365;--primary-light-color: #ff94bd;--primary-dark-color: #530020;--secondary-color:#6b46c1;--secondary-light-color: #ceb9ff;--secondary-dark-color: #311e6d;--tertiary-color:#2ee9b4;--tertiary-light-color: #a4ffe5;--tertiary-dark-color:#004d37;--success-color: #75c38f;--success-light-color:#e5f7ec;--success-dark-color:#315542;--warning-color: #ffc400;--warning-light-color: #fbf6b4;--warning-dark-color: #663d1d;--danger-color:#ff3838;--danger-light-color: #f7e7e6;--danger-dark-color: #950000;--soft-color: #fff;--soft-light-color: transparent;--soft-dark-color: #e6e6e6;--neutral-color: #b3b3b3;--neutral-light-color: #e7e7e7;--neutral-dark-color: #999999;--heavy-color: #282c34;--heavy-light-color: #575f70;--heavy-dark-color:#0d0f11}@media (min-width: 0px){.bci1{border-color:var(--primary-color);border-width:1px;border-style:solid}.bcm2{border-color:var(--neutral-color);border-width:1px;border-style:solid}.bcm2t{border-top-color:var(--neutral-color);border-top-width:1px;border-top-style:solid}.bgi1{background-color:var(--primary-color)}.bgm1{background-color:var(--soft-color)}.bgm2{background-color:var(--neutral-color)}.ci1{color:var(--primary-color)}.cm1{color:var(--soft-color)}.cm2z{color:var(--neutral-dark-color)}.cm3{color:var(--heavy-color)}.bgm1\:h:hover{background-color:var(--soft-color)}.ci1\:h:hover{color:var(--primary-color)}}@media (max-width: 768px){.sm\-bcm2t{border-top-color:var(--neutral-color);border-top-width:1px;border-top-style:solid}.sm\-bcm2b{border-bottom-color:var(--neutral-color);border-bottom-width:1px;border-bottom-style:solid}}@media (min-width: 768px){.md\+bci1{border-color:var(--primary-color);border-width:1px;border-style:solid}.md\+bcm2t,.md\+bcm2y{border-top-color:var(--neutral-color);border-top-width:1px;border-top-style:solid}.md\+bcm2y{border-bottom-color:var(--neutral-color);border-bottom-width:1px;border-bottom-style:solid}.md\+bgi1\:h:hover{background-color:var(--primary-color)}.md\+cm1\:h:hover{color:var(--soft-color)}}:root{--border-radius: 0.25rem}:root{--opacity: 0.05}@media (min-width: 0px){.op18{opacity:calc(18 * var(--opacity))}}:root{--letter-spacing: 0.1px}@media (min-width: 0px){.ls12{letter-spacing:calc(12 * var(--letter-spacing))}} - -@font-face{font-family:'Roboto';font-style:normal;font-weight:300;src:local(""),url("/roboto-v20-latin-300.woff2") format("woff2");font-display:swap}@font-face{font-family:'Roboto';font-style:normal;font-weight:500;src:local(""),url("/roboto-v20-latin-500.woff2") format("woff2");font-display:swap}@font-face{font-family:'Crete Round';font-style:normal;font-weight:400;src:local(""),url("/crete-round-v9-latin-regular.woff2") format("woff2");font-display:swap}.light{--primary-font-family: 'Crete Round', serif;--secondary-font-family: 'Roboto', sans-serif;--primary-color: #d22365;--soft-color: #fff;--neutral-color: #f0f0f2;--heavy-color: #282c34;--warning-color: #ffffd6}.dark{--primary-font-family: 'Crete Round', serif;--secondary-font-family: 'Roboto', sans-serif;--primary-color: #ddbc72;--soft-color: #2c3748;--neutral-color: #282c34;--heavy-color: #fff;--warning-color: #ffffd6}body{font-family:var(--secondary-font-family);font-weight:300;overflow-y:scroll}h1,h2,h3,h4{font-family:var(--primary-font-family);font-weight:700;letter-spacing:1px}strong{font-weight:700}blockquote{line-height:140%}section a img{transition:.1s}section a img:hover{transform:scale(1.1);z-index:1;transition:.3s}.bg-tagline-home{background-image:linear-gradient(0deg, var(--soft-color) 49%, rgba(107,107,107,0.4) 50%, var(--soft-color) 52%)}main{min-height:100vh;padding-top:70px}@media (min-width: 1600px){.lg-x12z{max-width:1400px}}pre{color:#ddbc72;font-size:1.2rem;width:100%;background-color:#282c34;line-height:1.5;padding:0.5rem;color:#ddbc72;overflow-x:auto}@-moz-document url-prefix(){pre{font-size:1.1rem}}@media (max-width: 768px){pre{overflow-x:auto}}.token.selector,.token.tag{color:#ff5d9a !important}.token.comment{color:#9dbcf7 !important}.token.string,.token.attr-value{color:#99c47a !important}.token.atrule,.token.keyword{color:#e89bff !important}.token.property,.token.boolean,.token.number,.token.constant,.token.symbol,.token.attr-name,.token.deleted{color:#e9ac72 !important}.token.function,.token.operator{color:#71bfff !important}.token.punctuation{color:#b1b8c6 !important}article :target::before{content:'';display:block;height:calc(80px + 1rem);margin-top:calc(-80px + -1rem)}article h2{margin-top:2rem}article p,article h2,article h3,article h4,article pre,article blockquote,article ul{margin-bottom:1rem}article ul{list-style-type:circle;padding-left:1.3rem}article li{padding:0.35rem 0}article a{color:var(--primary-color)}article h2 a,article h3 a{color:var(--heavy-color)}article em{font-weight:500;font-style:normal}article blockquote{border:1px solid var(--neutral-color);padding:0.5rem;margin-left:0}article blockquote p{margin-bottom:0}article code:not([class^=language]){font-size:1.1rem;vertical-align:1px;background:var(--neutral-color);padding:0 2px;border-radius:2px}@media (max-width: 768px){article pre code.language-jsx{overflow-x:scroll}} - diff --git a/docs/client-9cdb5778f42a90a83e1427c9316c97d3.js b/docs/client-9cdb5778f42a90a83e1427c9316c97d3.js deleted file mode 100644 index aa64a7a0..00000000 --- a/docs/client-9cdb5778f42a90a83e1427c9316c97d3.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){var t={};function __webpack_require__(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,__webpack_require__),r.l=!0,r.exports}__webpack_require__.m=e,__webpack_require__.c=t,__webpack_require__.d=function(e,t,n){__webpack_require__.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},__webpack_require__.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.t=function(e,t){if(1&t&&(e=__webpack_require__(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(__webpack_require__.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)__webpack_require__.d(n,r,function(t){return e[t]}.bind(null,r));return n},__webpack_require__.n=function(e){var t=e&&e.__esModule?function getDefault(){return e.default}:function getModuleExports(){return e};return __webpack_require__.d(t,"a",t),t},__webpack_require__.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=3)}([function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);n(0);const r=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/,i=/^\/Date\((d|-|.*)\)[\/|\\]$/;function dateParser(e,t){if("string"==typeof t){let e=r.exec(t);if(e)return new Date(t);if(e=i.exec(t),e){const t=e[1].split(/[-+,.]/);return new Date(t[0]?+t[0]:0-+t[1])}}return t}function deserialize(e){return JSON.parse(e,dateParser)}function fragment({children:e}){return e}function element_element(e,t,...n){n=function flattenChildren(e){return e=[].concat.apply([],e).map(e=>null!=e&&e),[].concat.apply([],e)}(n),"textarea"===e&&(n=[n.join("")]);const r={...t,children:n};return"element"===e&&(e=r.tag||fragment,delete r.tag),"function"==typeof e&&void 0!==e.render?{type:e,attributes:r,children:null}:{type:e,attributes:r,children:n}}function extractParamValue(e){return"true"===e||"false"!==e&&(e?decodeURIComponent(e.replace(/\+/g," ")):"")}function serializeParam(e){return e&&void 0!==e.toJSON?e.toJSON():e}function serializeSearch(e){return Object.keys(e).map(t=>!1===e[t]||e[t]?`${t}=${e[t]}`:"").filter(e=>!!e).join("&")}const a={};var s=a;const l={set(e,t,n){const r=serializeParam(n);e[t]=r;const i=serializeSearch(e);return L.url=L.path+(i?"?":"")+i,!0},get:(e,t)=>!1!==e[t]&&(!1!==s[t]&&(e[t]||s[t]||""))},o={...window.params};delete window.params;const c=new Proxy(o,l);function updateParams(e){!function resetSegments(){for(const e in a)delete a[e]}();const t=function getQueryStringParams(e){const[t,n]=e.split("?");return n?n.split("&").reduce((e,t)=>{let[n,r]=t.split("=");return e[n]=extractParamValue(r),e},{}):{}}(e);for(const e of Object.keys({...t,...o}))o[e]=t[e];return c}var u=c;const d={...window.environment,client:!0,server:!1};Object.freeze(d);var m=d;function extractLocation(e){let[t,n]=e.split("#"),[r,i]=t.split("?");"/"!==r&&r.endsWith("/")&&(r=r.substring(0,r.length-1));let a=r;i&&(a+="?"+i);let s=a;return n&&(s+="#"+n),void 0===n&&(n=""),{path:r,search:i,url:a,urlWithHash:s,hash:n}}function isFalse(e){return null==e||!1===e||!1===e.type}function isText(e){return void 0===e.children}function anchorableElement(e){const t=e.querySelectorAll('a[href^="/"]:not([target])');for(const e of t)e.onclick=t=>{t.preventDefault(),L.url=e.getAttribute("href")}}function render(e,t){if(isFalse(e)||"head"===e.type)return document.createComment("");if(isText(e))return document.createTextNode(e);const n=t&&t.svg||"svg"===e.type;let r;r=n?document.createElementNS("http://www.w3.org/2000/svg",e.type):document.createElement(e.type),e.instance&&(e.instance._self.element=r);for(let t in e.attributes)if("html"===t)r.innerHTML=e.attributes[t],anchorableElement(r);else if(t.startsWith("on")){const n=t.replace("on",""),i="_event."+n;e[i]=n=>{!0!==e.attributes.default&&n.preventDefault(),e.attributes[t]({...e.attributes,event:n})},r.addEventListener(n,e[i])}else{const n=typeof e.attributes[t];"object"!==n&&"function"!==n&&("value"!=t&&!0===e.attributes[t]?r.setAttribute(t,""):("value"==t||!1!==e.attributes[t]&&null!==e.attributes[t]&&void 0!==e.attributes[t])&&r.setAttribute(t,e.attributes[t]))}if(!e.attributes.html){for(let t=0;t{!0!==n.attributes.default&&e.preventDefault(),n.attributes[i]({...n.attributes,event:e})},e.addEventListener(r,n[a]))}else{const r=typeof n.attributes[i];"object"!==r&&"function"!==r&&(void 0!==t.attributes[i]&&void 0===n.attributes[i]?e.removeAttribute(i):t.attributes[i]!==n.attributes[i]&&("value"!=i&&!1===n.attributes[i]||null===n.attributes[i]||void 0===n.attributes[i]?e.removeAttribute(i):"value"!=i&&!0===n.attributes[i]?e.setAttribute(i,""):e.setAttribute(i,n.attributes[i])))}if(n.attributes.html)return;const i=Math.max(t.children.length,n.children.length);if(n.children.length>t.children.length){for(let r=0;rn.children.length){for(let r=0;r=n.children.length;r--)e.removeChild(e.childNodes[r])}else for(let r=i-1;r>-1;r--)rerender(e.childNodes[r],t.children[r],n.children[r]);"textarea"==n.type&&(e.value=n.children.join("")),"select"==n.type&&(e.value=n.attributes.value)}}}}function isProxyable(e,t){return!(e.startsWith("_")||null===t||"object"!=typeof t||void 0!==t._isProxy||t instanceof Date)}var h={set(e,t,n){return isProxyable(t,n)?(n._isProxy=!0,e[t]=new Proxy(n,this)):e[t]=n,t.startsWith("_")||x.update(),!0}};const p=deserialize(JSON.stringify(window.context)),f={set(e,t,n){return isProxyable(t,n)?(n._isProxy=!0,p[t]=new Proxy(n,h)):p[t]=n,x.update(),Reflect.set(...arguments)},get:(e,t)=>void 0===e[t]?p[t]:e[t]};function generateContext(e){return new Proxy(e,f)}var b=p;function erase(e){e.type=!1,delete e.attributes,delete e.children}function camelize(e){return e.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g,(e,t)=>t.toUpperCase())}function kebabize(e){return e.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,"$1-$2").toLowerCase()}let y=[{transform:function objectable_transform({node:e}){if(function objectable_match(e){return e&&void 0!==e.attributes}(e))for(const t in e.attributes)if(t.startsWith("on")&&"object"==typeof e.attributes[t]){const n=e.attributes.source,r=e.attributes[t];e.attributes[t]=function(){Object.assign(n,r)}.bind(n)}},client:!0},{transform:function parameterizable_transform({node:e,router:t,params:n}){if(!function parameterizable_match(e){return e&&e.attributes&&(e.attributes.params||e.attributes.path)}(e))return;let r;if(e.attributes.params){r={};for(const t in e.attributes.params)r[t]=serializeParam(e.attributes.params[t])}else r=n;const i=serializeSearch(r),a=e.attributes.path||t.path;e.attributes.href=a+(i?"?":"")+i,delete e.attributes.path,delete e.attributes.params},client:!0,server:!0},{transform:function anchorable_transform({node:e,router:t}){if(!function anchorable_match(e){return e&&"a"===e.type&&e.attributes.href&&e.attributes.href.startsWith("/")&&!e.attributes.target}(e))return;const n=e.attributes.onclick;e.attributes.onclick=({event:r})=>{r.preventDefault(),t.url=e.attributes.href,n&&setTimeout(()=>{n({...e.attributes,event:r})},0)}},client:!0},{load:function load({router:e}){e._routes={},e._oldSegments?(e._oldSegments=e._newSegments,e._newSegments={}):(e._oldSegments={},e._newSegments={})},transform:function routable_transform({node:e,depth:t,router:n}){if(!function match(e){return e&&void 0!==e.attributes&&void 0!==e.attributes.route}(e))return;const r=t.slice(0,-1).join(".");if(void 0!==n._routes[r])erase(e);else{const t=function routeMatches(e,t){let{path:n}=extractLocation(e);const r=n.split("/"),i=t.split("/"),a={},s=Math.max(r.length,i.length);let l=!1;for(let e=0;e{"checked"==r?t[e.attributes.bind]=n.target[r]:!0===t[e.attributes.bind]||!1===t[e.attributes.bind]?t[e.attributes.bind]=n?"true"==n.target[r]:a:"number"==typeof t[e.attributes.bind]?t[e.attributes.bind]=parseFloat(n?n.target[r]:a)||0:t[e.attributes.bind]=n?n.target[r]:a,void 0!==i&&setTimeout(()=>{i({...e.attributes,event:n,value:a})},0)}}(e)},client:!0,server:!0}];function loadPlugins(e){for(const t of y)t.load&&t.load(e.context);return y}async function generateBranch(e,t,n,r){if(function transformNodes(e,t,n){for(const r of y)r.transform({...e.context,node:t,depth:n})}(r,t,n),function isClass(e){return"function"==typeof e.type&&e.type.prototype&&"function"==typeof e.type.prototype.render}(t)){const i=t.attributes.key||function generateKey(e){return 1===e.length?"application":"n-"+e.join("-")}(n);if(r.context.environment.client&&r.context.router._changed&&t.attributes&&t.attributes.route&&!r.context.environment.static){const e=n.slice(0,-1).join("."),t=r.context.router._newSegments[e];if(t){const n=r.context.router._oldSegments[e];for(const e in t)n[e]!==t[e]&&(delete r.memory[i],delete r.instances[i])}}const a=r.instances[i]||new t.type(r);let s;a._self.key=i,a._attributes=t.attributes,a._scope=r,r.memory&&(s=r.memory[i],s&&(a._self.initiated=!0,Object.assign(a,s),delete r.memory[i]));let l=!1;const o=void 0===r.instances[i];r.instances[i]=a,o&&(void 0===s&&(a.prepare&&a.prepare(),r.context.environment.server?(a.initiate&&await a.initiate(),a._self.initiated=!0):r.initiationQueue.push(a)),l=!0),r.hydrationQueue&&(l?r.hydrationQueue.push(a):1==a._self.initiated&&a.update&&a.update()),r.context.environment.client&&r.renewalQueue.push(a);const c=a.render();c&&c.type&&(c.instance=a),t.children=[].concat(c);for(let i=0;i{const e=g;e.context=b,e.plugins=loadPlugins(e),g.initialized=!1,g.initiationQueue=[],g.renewalQueue=[],g.hydrationQueue=[],g.nextVirtualDom=await generateTree(g.initializer(),e),rerender(g.selector),g.virtualDom=g.nextVirtualDom,g.nextVirtualDom=null,g.processLifecycleQueues()},16))},g.processLifecycleQueues=async function(){g.initialized||(g.initialized=!0,g.hydrated=!0);const e=g.initiationQueue,t=g.hydrationQueue;for(const t of e)t.initiate&&await t.initiate(),t._self.initiated=!0;e.length&&g.update();for(const e of t)e.hydrate&&await e.hydrate(),e._self.hydrated=!0;t.length&&g.update();for(const e in g.instances){const t=g.instances[e];g.renewalQueue.includes(t)||(t.terminate&&await t.terminate(),delete g.instances[e])}L._changed=!1};var x=g;const _={...window.worker};_.online=navigator.onLine,delete window.worker;const v=Object.freeze([]),w={set:(e,t,n)=>(e[t]=n,x.update(),!0),get:(e,t)=>e[t]||v};_.queues=new Proxy({},w);const k=new Proxy(_,{set:(e,t,n)=>(e[t]!==n&&(e[t]=n,x.update()),!0)});if(_.enabled){window.addEventListener("beforeinstallprompt",(function(e){e.preventDefault(),k.installation=e})),async function register(){if("serviceWorker"in navigator){const e=`/service-worker-${m.key}.js`;try{k.registration=await navigator.serviceWorker.register(e,{scope:"/"})}catch(e){console.log(e)}}}()}window.addEventListener("online",()=>{k.online=!0,m.static?L._update(L.url):k.responsive=!0}),window.addEventListener("offline",()=>{k.online=!1});var P=k;function windowEvent(e){clearTimeout(null),setTimeout(()=>{const t=new Event("nullstack."+e);window.dispatchEvent(t)},0)}const j={...window.page,event:"nullstack.page"};delete window.page;var C=new Proxy(j,{set(e,t,n){"title"===t&&(document.title=n);const r=Reflect.set(...arguments);return"title"===t&&windowEvent("page"),x.update(),r}});function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}let S=null;var L=new class router_Router{constructor(){_defineProperty(this,"event","nullstack.router"),_defineProperty(this,"_changed",!1),_defineProperty(this,"_segments",s);const{hash:e,url:t}=extractLocation(window.location.pathname+window.location.search);this._url=t,this._hash=e}async _popState(){const{urlWithHash:e}=extractLocation(window.location.pathname+window.location.search);await this._update(e,!1)}async _update(e,t){const{url:n,path:r,hash:i,urlWithHash:a}=extractLocation(e);clearTimeout(S),S=setTimeout(async()=>{if(C.status=200,m.static){P.fetching=!0;const e="/index.json",t="/"===r?e:r+e;try{const e=await fetch(t),r=await e.json(n);x.memory=r.instances;for(const e in r.page)C[e]=r.page[e];P.responsive=!0}catch(e){P.responsive=!1}P.fetching=!1}t&&history.pushState({},document.title,a),this._url=n,this._hash=i,this._changed=!0,updateParams(n),x.update(),windowEvent("router")},0)}async _redirect(e){const{url:t,hash:n,urlWithHash:r}=extractLocation(e);t===this._url&&this._hash===n||await this._update(r,!0),n||window.scroll(0,0)}get url(){return this._url}set url(e){this._redirect(e)}get path(){return extractLocation(this._url).path}set path(e){this._redirect(e+window.location.search)}};var q={get(e,t){return"function"!=typeof e[t]||e[t].name.startsWith("_")||"constructor"===t?Reflect.get(...arguments):n=>{const r=generateContext({...e._attributes,...n,self:e._self});return e[t](r)}},set:(e,t,n)=>(isProxyable(t,n)?(n._isProxy=!0,e[t]=new Proxy(n,h)):e[t]=n,t.startsWith("_")||x.update(),!0)};const O={...window.settings};delete window.settings,Object.freeze(O);var T=O;const A={...window.project};delete window.project,Object.freeze(A);var z=A;function client_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}b.page=C,b.router=L,b.settings=T,b.worker=P,b.params=u,b.project=z,b.environment=window.environment,x.memory=deserialize(JSON.stringify(window.instances));const H=x;H.generateContext=generateContext,H.context=b,x.plugins=loadPlugins(H);class client_Nullstack{static async start(e){window.addEventListener("popstate",()=>{L._popState()}),x.routes={},updateParams(L.url),x.currentInstance=null,x.initializer=()=>element_element(e),x.selector=document.querySelector("#application"),x.virtualDom=await generateTree(x.initializer(),H),b.environment=m,H.plugins=loadPlugins(H),x.nextVirtualDom=await generateTree(x.initializer(),H),rerender(x.selector),x.virtualDom=x.nextVirtualDom,x.nextVirtualDom=null,x.processLifecycleQueues(),delete window.context}constructor(){client_defineProperty(this,"_self",{prerendered:!1,initiated:!1,hydrated:!1});const e=function getProxyableMethods(e){let t=new Set,n=e;do{Object.getOwnPropertyNames(n).map(e=>t.add(e))}while((n=Object.getPrototypeOf(n))&&n!=Object.prototype);return[...t.keys()].filter(t=>"constructor"!==t&&"function"==typeof e[t]&&!t.startsWith("_")&&!e[t].name.startsWith("_"))}(this),t=new Proxy(this,q);for(const n of e)this[n]=this[n].bind(t);return t}render(){return!1}}client_defineProperty(client_Nullstack,"element",element_element),client_defineProperty(client_Nullstack,"invoke",(function invoke(e,t){return async function _invoke(n={}){var r;let i;P.fetching=!0,Object.isFrozen(P.queues[e])?P.queues[e]=[n]:P.queues[e]=[...P.queues[e],n];let a=`/nullstack/${t===this.constructor.hash?t:`${t}-${this.constructor.hash}`}/${e}.json`;try{const e=await fetch(a,{method:"POST",headers:P.headers,mode:"cors",cache:"no-cache",credentials:"same-origin",redirect:"follow",referrerPolicy:"no-referrer",body:JSON.stringify(n||{})});C.status=e.status;i=deserialize(await e.text()).result,P.responsive=!0}catch(e){P.responsive=!1}return 1===(null===(r=P.queues[e])||void 0===r?void 0:r.length)?delete P.queues[e]:P.queues[e]=P.queues[e].filter(e=>e!==n),P.fetching=!!Object.keys(P.queues).length,i}})),client_defineProperty(client_Nullstack,"fragment",fragment),client_defineProperty(client_Nullstack,"use",function usePlugins(e){return async(...t)=>{y=[...new Set([...t.flat(),...y])].filter(t=>t[e])}}("client"));var M=client_Nullstack;n(1);function Translatable_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class Translatable_Translatable extends M{constructor(...e){super(...e),Translatable_defineProperty(this,"geti18nByLocale",M.invoke("geti18nByLocale","9d29dc34ec2fb3d34927d978fe04a63f"))}async initiate({project:e,page:t,locale:n}){this.locale=n,this.i18n=await this.geti18nByLocale({locale:n}),this.i18n.title&&(t.title=`${this.i18n.title} - ${e.name}`,t.description=this.i18n.description,t.locale=n||"en-US")}update({locale:e}){this.locale!==e&&this.initiate()}}Translatable_defineProperty(Translatable_Translatable,"hash","9d29dc34ec2fb3d34927d978fe04a63f");var N=Translatable_Translatable;class Documentation_Documentation extends N{prepare({page:e}){e.priority=.8}renderLink({title:e,href:t}){return M.element("a",{href:t,title:e,class:"xl x12 p3y bcm2t ci1"}," ",e," ")}renderTopic({title:e,description:t,links:n}){const r=this.renderLink;return M.element("div",{class:"x12 m6y bcm2 p4x p4t p1b"},M.element("h2",{class:"x12 sm-fs6 md+fs8 m2b"}," ",e," "),M.element("p",{class:"x12 fs4 m6b"}," ",t," "),M.element("nav",{class:"x12"},n.map(e=>M.element(r,e))))}render(){const e=this.renderTopic;return!!this.i18n&&M.element("section",{class:"x sm-p4x sm-p10y md+p20y"},M.element("h1",{class:"x12 sm-fs6 md+fs12 m2b"}," ",this.i18n.heading," "),M.element("p",{class:"x12 fs4"}," ",this.i18n.tagline," "),M.element("div",{class:"x12"},this.i18n.topics.map(t=>M.element(e,t))))}}!function Documentation_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Documentation_Documentation,"hash","ad78cd7fc5dfcebd15f3ff1ead146a8f");var W=Documentation_Documentation;class Components_Components extends N{prepare({page:e}){e.priority=.3}renderProject({title:e,repository:t}){return M.element("a",{href:t,target:"_blank",rel:"noopener",class:"xl x12 p3y bcm2t ci1"},e)}renderTopic({title:e,projects:t,tagline:n}){const r=this.renderProject;return M.element("div",{class:"x12 m6y bcm2 p4x p4t p1b"},M.element("h2",{class:"x12 sm-fs6 md+fs8 m3b"}," ",e," "),n&&M.element("p",{class:"m3y",title:n.title}," ",n.text," "),M.element("nav",{class:"x12"},t.map(e=>M.element(r,e))))}render(){const e=this.renderTopic;return!!this.i18n&&M.element("section",{class:"x sm-p4x sm-p10y md+p20y"},M.element("h1",{class:"x12 sm-fs6 md+fs12 m2b"}," ",this.i18n.heading," "),M.element("p",{class:"x12 fs4"}," ",this.i18n.tagline," "),M.element("p",{class:"m2t",html:this.i18n.contribute}),M.element("div",{class:"x12"},this.i18n.topics.map(t=>M.element(e,t))))}}!function Components_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Components_Components,"hash","772783a04f255f1a890e0bcf1316682d");var D=Components_Components;n(2);function Article_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class Article_Component extends M{constructor(...e){super(...e),Article_defineProperty(this,"title",""),Article_defineProperty(this,"html",""),Article_defineProperty(this,"getArticleByKey",M.invoke("getArticleByKey","37dcb598ed5094b0f85b47b5e3756ca4"))}async initiate({project:e,page:t,locale:n,params:r}){const i=await this.getArticleByKey({key:r.slug,locale:n});Object.assign(this,i),t.title=`${i.title} - ${e.name}`,t.description=i.description,i.status&&(t.status=404)}render(){return M.element("section",{class:"x sm-p4x sm-p10y md+p20y"},M.element("h1",{class:"x12 sm-fs6 md+fs8 m6b"}," ",this.title," "),M.element("article",{html:this.html}))}}Article_defineProperty(Article_Component,"hash","37dcb598ed5094b0f85b47b5e3756ca4");var B=Article_Component;function Logo({light:e,height:t,monotone:n}){const r=e?"#fff":"#2d3748",i=n?r:"#d22365";return M.element("svg",{xmlns:"http://www.w3.org/2000/svg",height:t,viewBox:"0 0 511.5039 113.7368"},M.element("title",null," Nullstack "),M.element("path",{d:"M13.2736,39.964H28.7009v9.8922a20.3919,20.3919,0,0,1,7.743-8.479,21.2792,21.2792,0,0,1,11.2172-3.0031q7.36,0,11.3349,4.1218t3.9745,11.6588a48.9655,48.9655,0,0,1-1.06,8.8913l-8.3025,42.8665H36.3556L44.187,65.7546a31.2306,31.2306,0,0,0,.5888-5.5939q0-7.6542-6.3593-7.6547a10.7348,10.7348,0,0,0-8.4791,4.3278q-3.5922,4.328-5.0639,12.0415l-7.1248,37.0372H.4961Z",transform:"translate(-0.4961)",fill:r}),M.element("path",{d:"M81.4691,107.62q-7.2426,0-11.2466-4.1807t-4.004-11.8943a46.3965,46.3965,0,0,1,1.001-8.6557L75.64,39.964H92.7746L85.0609,80.24a29.8175,29.8175,0,0,0-.5888,5.5938q0,7.6551,6.4771,7.6548A10.3547,10.3547,0,0,0,99.2811,89.19q3.4446-4.2978,4.9756-12.0709L111.44,39.964h17.1348l-12.7775,65.9485H100.37V96.138a18.7565,18.7565,0,0,1-7.4781,8.3908A21.4849,21.4849,0,0,1,81.4691,107.62Z",transform:"translate(-0.4961)",fill:r}),M.element("path",{d:"M150.2958,113.7368q-11.4821,0-16.7815-3.3563t-5.2995-10.5989a43.049,43.049,0,0,1,1.1188-8.3613l11.9532-56.6451H123.2687l2.532-13.2486h35.2118L146.2918,92.4213q-.1767.825-.3238,1.7371a10.5763,10.5763,0,0,0-.1473,1.6781q0,4.6521,8.2436,4.6517h16.3694l-2.65,13.2486Z",transform:"translate(-0.4961)",fill:i}),M.element("path",{d:"M181.897,92.21q-11.4822,0-16.7816-3.3563T159.816,78.255a43.0455,43.0455,0,0,1,1.1187-8.3613l11.9532-56.6451H154.87L157.4018,0h35.2118L177.8929,70.8947q-.1765.8248-.3238,1.737a10.5766,10.5766,0,0,0-.1472,1.6782q0,4.6519,8.2435,4.6517h16.3694l-2.65,13.2486Z",transform:"translate(-0.4961)",fill:i}),M.element("path",{d:"M228.3106,107.62a72.47,72.47,0,0,1-23.6119-4.1218l3.003-15.0739q10.5988,6.7717,21.6688,6.7715,6.4176,0,10.0983-2.2965a7.1387,7.1387,0,0,0,3.68-6.3593,4.4873,4.4873,0,0,0-1.8253-3.8273q-2.3556-1.884-9.5979-3.9452l-5.1817-1.4132q-13.8969-3.8271-13.8963-16.9582a18.9819,18.9819,0,0,1,8.0375-16.0455q8.0374-5.976,22.4637-5.9766a60.6829,60.6829,0,0,1,10.1573.8538,63.0434,63.0434,0,0,1,10.5105,2.797L260.8727,56.981a33.7,33.7,0,0,0-19.3724-6.3q-5.9478,0-9.3623,2.09a6.2659,6.2659,0,0,0-3.4152,5.5056,5.102,5.102,0,0,0,2.2375,4.2984q2.4731,1.7082,9.6568,3.7685l4.3573,1.2365q7.4775,2.12,10.9816,6.271t3.5035,10.805q0,10.7172-8.2436,16.84T228.3106,107.62Z",transform:"translate(-0.4961)",fill:r}),M.element("path",{d:"M297.9546,106.2069q-11.3055,0-16.6932-3.3857t-5.3878-10.57a47.7847,47.7847,0,0,1,1.06-8.3613l5.9472-30.6778H265.9813l2.532-13.2486h16.8993l3.5918-18.7247h17.2527L302.6063,39.964h22.5521l-2.532,13.2486h-22.552l-6.1827,31.6788A20.2915,20.2915,0,0,0,293.48,88.13a3.9534,3.9534,0,0,0,1.9431,3.68q1.9433,1.1482,6.2416,1.1482h13.2486l-2.532,13.2486Z",transform:"translate(-0.4961)",fill:r}),M.element("path",{d:"M338.2138,107.62q-9.4224,0-14.6029-5.1228-5.1828-5.1228-5.1816-14.25,0-12.2469,9.3034-18.99t26.2617-6.7421h11.3643l.4711-2.8852a3.6427,3.6427,0,0,1,.1177-.7066v-1.001A5.6271,5.6271,0,0,0,362.974,52.8q-2.9748-1.7666-8.5086-1.7665a41.5275,41.5275,0,0,0-10.8933,1.59,85.9338,85.9338,0,0,0-13.3074,5.0639l2.7675-14.7206a74.3941,74.3941,0,0,1,24.6129-4.5929q12.07,0,18.6363,4.6518,6.5643,4.652,6.5655,13.72a36.323,36.323,0,0,1-.4711,5.5939q-.4716,3.003-1.1188,5.9471l-7.2425,37.626H358.47v-7.36A26.3115,26.3115,0,0,1,338.2138,107.62Zm7.1837-11.8354q6.476,0,11.2466-5.6822t6.3-15.3978h-6.6537q-19.9029,0-19.9023,12.13a8.3352,8.3352,0,0,0,9.009,8.95Z",transform:"translate(-0.4961)",fill:r}),M.element("path",{d:"M415.1828,107.62q-13.72,0-21.1683-7.4192t-7.4486-21.4333a42.63,42.63,0,0,1,5.005-20.8444,36.7663,36.7663,0,0,1,13.9257-14.338,40.3978,40.3978,0,0,1,20.7562-5.2111A39.0215,39.0215,0,0,1,445.8607,43.32l-3.1208,15.78a22.7112,22.7112,0,0,0-16.075-6.7126,21.2393,21.2393,0,0,0-11.8059,3.2974A22.52,22.52,0,0,0,406.88,64.783a29.416,29.416,0,0,0-2.8853,13.278q0,8.0083,3.4741,11.7765T417.95,93.606q8.8324,0,19.3724-6.1238l-3.2974,16.2516A45.998,45.998,0,0,1,415.1828,107.62Z",transform:"translate(-0.4961)",fill:r}),M.element("path",{d:"M458.1224,14.2911H475.375l-8.95,46.0463L490.2134,39.964H512L482.2643,64.5769l18.43,41.3356H482.382L469.31,75.058l-6.83,5.6527-4.8284,25.2018H440.3987Z",transform:"translate(-0.4961)",fill:r}))}class stroke_Icon extends M{render({width:e,height:t,length:n,title:r,rotation:i,animation:a,speed:s,class:l,color:o="currentColor"}){const c=!!i&&`rotate(${i})`,u={slow:"1.5s",fast:"0.5s"}[s]||"1.0s";return M.element("svg",{width:e,height:t,transform:c,class:l,viewBox:"0 0 512 512"},r&&M.element("title",null,r),"spin"===a&&M.element("animateTransform",{attributeType:"xml",attributeName:"transform",type:"rotate",from:"360 0 0",to:"0 0 0",dur:u,additive:"sum",repeatCount:"indefinite"}),M.element("rect",{x:"10",y:"10",width:"492",height:"90.4043",rx:"17.383","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("rect",{x:"10",y:"411.5957",width:"492",height:"90.4043",rx:"17.383","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("rect",{x:"10",y:"210.7979",width:"492",height:"90.4043",rx:"17.383","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}))}}!function stroke_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(stroke_Icon,"hash","5108bffdb18ff08ed57d8863e428a0a6");var $=stroke_Icon;class ex_stroke_Icon extends M{render({width:e,height:t,length:n,title:r,rotation:i,animation:a,speed:s,class:l,color:o="currentColor"}){const c=!!i&&`rotate(${i})`,u={slow:"1.5s",fast:"0.5s"}[s]||"1.0s";return M.element("svg",{width:e,height:t,transform:c,class:l,viewBox:"0 0 512 512"},r&&M.element("title",null,r),"spin"===a&&M.element("animateTransform",{attributeType:"xml",attributeName:"transform",type:"rotate",from:"360 0 0",to:"0 0 0",dur:u,additive:"sum",repeatCount:"indefinite"}),M.element("path",{d:"M335.1385,256,495.697,95.4415a21.52,21.52,0,0,0,0-30.4336L446.9921,16.303a21.52,21.52,0,0,0-30.4336,0L256,176.8615,95.4415,16.303a21.52,21.52,0,0,0-30.4336,0L16.303,65.0079a21.52,21.52,0,0,0,0,30.4336L176.8615,256,16.303,416.5585a21.52,21.52,0,0,0,0,30.4336L65.0079,495.697a21.52,21.52,0,0,0,30.4336,0L256,335.1385,416.5585,495.697a21.52,21.52,0,0,0,30.4336,0l48.7049-48.7049a21.52,21.52,0,0,0,0-30.4336Z",transform:"translate(0 0)",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}))}}!function ex_stroke_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(ex_stroke_Icon,"hash","c92162c171095d8fb7c2650c3b647d5b");var E=ex_stroke_Icon;function Header_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class Header_Header extends N{constructor(...e){super(...e),Header_defineProperty(this,"expanded",!1)}renderLink({title:e,href:t,target:n,onclick:r}){return M.element("element",{tag:t?"a":"button",href:t,target:n,source:this,onclick:r||!n&&{expanded:!1},rel:!!n&&"noopener",class:"sm-x12 sm-bcm2b p2 fs4 ci1:h yy"}," ",e," ")}toggleMode(e){const t=e.mode;e.mode=e.oppositeMode,e.oppositeMode=t,window.localStorage.setItem("mode",e.mode)}render({mode:e,oppositeMode:t}){const n=this.renderLink;return!!this.i18n&&M.element("header",{class:"x12 pftl bgm1 bs2"},M.element("div",{class:"x xsb yy p5y"},M.element("div",{class:"sm-x12 sm-xsb sm-p4x yy"},M.element("a",this.i18n.home,M.element(Logo,{height:"30",light:"dark"===e})),M.element("span",{source:this,onclick:{expanded:!this.expanded},class:"yy md+off"},M.element("element",{tag:this.expanded?E:$,height:20,class:"cm3"}))),M.element("nav",{class:"menu-links yy sm-p4 "+(!this.expanded&&"sm-off")},this.i18n.links.map(e=>M.element(n,e)),M.element(n,{title:this.i18n.mode[t],source:this,onclick:this.toggleMode})),M.element("div",{class:"sm-x12 sm-p4x "+(!this.expanded&&"sm-off")},M.element("a",{href:this.i18n.action.href,source:this,onclick:{expanded:!1},class:"xx sm-x12 bci1 bgi1 bgm1:h cm1 ci1:h p4x p2y"},this.i18n.action.title))))}}Header_defineProperty(Header_Header,"hash","48bcd064d7d1302b252f990b780110fa");var F=Header_Header;class Footer_Footer extends N{renderLink({title:e,href:t}){return M.element("a",{href:t,rel:"noopener",target:"_blank",class:"sm-xr sm-m1y sm-x12 md+bci1 sm-bcm2t sm-p4t ci1 md+cm1:h md+bgi1:h p4x p2y md+m2x"},e)}render({locale:e}){const t=this.renderLink;if(!this.i18n)return!1;const n="en-US"!==e?"/"+e.toLowerCase():"";return M.element("footer",{class:"xx m20t"},M.element("div",{class:"x xr md+bcm2t yy md+p10y prtl"},M.element("a",{href:n+"/waifu"},M.element("img",{src:"/nullachan.png",alt:this.i18n.nullachan.alt,title:this.i18n.nullachan.title,class:"pabl sm-p2l",height:"160",loading:"lazy"})),M.element("nav",{class:"xr sm-x4 yy"},this.i18n.links.map(e=>M.element(t,e)))))}}!function Footer_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Footer_Footer,"hash","5b01fe21e147e009e4da5a163b0562db");var I=Footer_Footer;function Snippet_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class Snippet_Snippet extends M{constructor(...e){super(...e),Snippet_defineProperty(this,"html",""),Snippet_defineProperty(this,"getSnippetByKey",M.invoke("getSnippetByKey","8553d9a44c718847666cf850c3664d8a"))}async initiate({key:e}){this.html=await this.getSnippetByKey({key:e})}render(){return M.element("pre",{class:"p4"},M.element("code",{html:this.html}))}}Snippet_defineProperty(Snippet_Snippet,"hash","8553d9a44c718847666cf850c3664d8a");var Q=Snippet_Snippet;class cog_stroke_Icon extends M{render({width:e,height:t,length:n,title:r,rotation:i,animation:a,speed:s,class:l,color:o="currentColor"}){const c=!!i&&`rotate(${i})`,u={slow:"1.5s",fast:"0.5s"}[s]||"1.0s";return M.element("svg",{width:e,height:t,transform:c,class:l,viewBox:"0 0 512 512"},r&&M.element("title",null,r),"spin"===a&&M.element("animateTransform",{attributeType:"xml",attributeName:"transform",type:"rotate",from:"360 0 0",to:"0 0 0",dur:u,additive:"sum",repeatCount:"indefinite"}),M.element("path",{d:"M501.9984,279.0708a16.0691,16.0691,0,0,1-13.4278,15.8986l-35.9968,5.9988A17.6011,17.6011,0,0,0,438.58,313.2018a190.8568,190.8568,0,0,1-13.0446,31.4643A17.5918,17.5918,0,0,0,426.82,363.09l21.2127,29.7891a16.0776,16.0776,0,0,1-1.7514,20.7457l-32.6594,32.6583a16.0432,16.0432,0,0,1-20.72,1.77l-29.6617-21.2007a17.59,17.59,0,0,0-18.5045-1.2931,192.38,192.38,0,0,1-31.5078,13.0457,17.6007,17.6007,0,0,0-12.1433,13.9121l-6.1141,36.0359a16.07,16.07,0,0,1-15.903,13.4484H232.82a16.0653,16.0653,0,0,1-15.8975-13.4277l-6-35.9967a17.6049,17.6049,0,0,0-12.1182-13.9633,191.0666,191.0666,0,0,1-30.5031-12.54,17.62,17.62,0,0,0-18.399,1.2888L119.709,448.852a15.4291,15.4291,0,0,1-9.2011,2.9509A15.7635,15.7635,0,0,1,99.1461,447.05l-32.7182-32.715a15.9459,15.9459,0,0,1-1.7394-20.626l21.0854-29.3308a17.5751,17.5751,0,0,0,1.255-18.6569,186.7013,186.7013,0,0,1-13.2112-31.3456A17.637,17.637,0,0,0,59.935,302.2907l-36.49-6.2208A16.0752,16.0752,0,0,1,10,280.168V234.0254a16.0757,16.0757,0,0,1,13.4571-15.902l35.5549-6a17.5854,17.5854,0,0,0,13.9763-12.2794,188.24,188.24,0,0,1,12.828-31.5448,17.6135,17.6135,0,0,0-1.2877-18.3989L63.09,119.78A16.0645,16.0645,0,0,1,64.82,99.0512l32.77-32.6584.1187-.124a15.6331,15.6331,0,0,1,11.2594-4.6469,15.8133,15.8133,0,0,1,9.3122,2.951l29.457,21.2039a17.5634,17.5634,0,0,0,18.6536,1.2507,186.6559,186.6559,0,0,1,31.3326-13.2068,17.6346,17.6346,0,0,0,12.0921-13.887l6.2252-36.49A16.0692,16.0692,0,0,1,231.9433,9.9987h46.1426a16.0748,16.0748,0,0,1,15.902,13.4571l6,35.5678a17.5926,17.5926,0,0,0,12.2968,13.9721,189.9907,189.9907,0,0,1,32.6888,13.4528,17.612,17.612,0,0,0,18.45-1.2714L393.28,63.9132a15.41,15.41,0,0,1,9.2011-2.9509,15.7748,15.7748,0,0,1,11.3618,4.7546l32.7138,32.7138a15.95,15.95,0,0,1,1.7144,20.6608L427.05,148.7826a17.6069,17.6069,0,0,0-1.2714,18.48,192.2247,192.2247,0,0,1,13.049,31.511,17.6,17.6,0,0,0,13.9121,12.139l36.0055,6.11.03.0043A15.6605,15.6605,0,0,1,501.9984,232.7Z",transform:"translate(0 0.0013)",fill:"none",stroke:o,"stroke-miterlimit":"10","stroke-width":n||20}),M.element("circle",{cx:"256",cy:"256.0013",r:"101",fill:"none",stroke:o,"stroke-miterlimit":"10","stroke-width":n||20}))}}!function cog_stroke_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(cog_stroke_Icon,"hash","fc9e1bed5737d04f2ad977b1c4cdb408");var Z=cog_stroke_Icon;class heartbeat_stroke_Icon extends M{render({width:e,height:t,length:n,title:r,rotation:i,animation:a,speed:s,class:l,color:o="currentColor"}){const c=!!i&&`rotate(${i})`,u={slow:"1.5s",fast:"0.5s"}[s]||"1.0s";return M.element("svg",{width:e,height:t,transform:c,class:l,viewBox:"0 0 512 512"},r&&M.element("title",null,r),"spin"===a&&M.element("animateTransform",{attributeType:"xml",attributeName:"transform",type:"rotate",from:"360 0 0",to:"0 0 0",dur:u,additive:"sum",repeatCount:"indefinite"}),M.element("path",{d:"M256.0491,165.8235c-6.0229-62.1643-55.5458-111.6161-113.0353-111.6161-61.5719,0-111.4858,55.5181-111.4858,124.0033,0,38.8968,16.1059,73.6046,41.2994,96.34l-.2914-.001L254.7788,457.7926,436.7424,275.829h-.0008c26.0153-22.7008,42.73-57.9881,42.73-97.6183,0-68.4852-49.9139-124.0033-111.4858-124.0033-57.8133,0-106.3487,48.947-111.9368,111.6161",transform:"translate(0 0)",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}),M.element("polyline",{points:"10 271.077 129.954 271.077 160.643 160.216 187.204 243.836 241.858 243.836 268.929 323.667 323.583 160.216 354.72 271.035 502 271.035",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}))}}!function heartbeat_stroke_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(heartbeat_stroke_Icon,"hash","e146fb21c8a4237c1abd3732575f5aa1");var R=heartbeat_stroke_Icon;class qrcode_stroke_Icon extends M{render({width:e,height:t,length:n,title:r,rotation:i,animation:a,speed:s,class:l,color:o="currentColor"}){const c=!!i&&`rotate(${i})`,u={slow:"1.5s",fast:"0.5s"}[s]||"1.0s";return M.element("svg",{width:e,height:t,transform:c,class:l,viewBox:"0 0 512 512"},r&&M.element("title",null,r),"spin"===a&&M.element("animateTransform",{attributeType:"xml",attributeName:"transform",type:"rotate",from:"360 0 0",to:"0 0 0",dur:u,additive:"sum",repeatCount:"indefinite"}),M.element("rect",{x:"74.1597",y:"73.5849",width:"151.0896",height:"151.2926",rx:"10.435","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("rect",{x:"286.7507",y:"73.5849",width:"151.0896",height:"151.2926",rx:"11.935","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("rect",{x:"74.1597",y:"286.4615",width:"151.0896",height:"151.2926",rx:"13.935","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("rect",{x:"284.7951",y:"284.5033",width:"85.677",height:"85.7921",rx:"7.935","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("rect",{x:"372.2824",y:"372.1081",width:"61.792",height:"61.875",rx:"1.6716","stroke-width":n||20,stroke:o,"stroke-linecap":"round","stroke-linejoin":"round",fill:"none"}),M.element("path",{d:"M124.4721,10.0426h-79.04S10,7.3135,10,45.5221v80.511",transform:"translate(0 0)",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}),M.element("path",{d:"M10.0426,387.3742v79.1464S7.3171,502,45.4744,502h80.403",transform:"translate(0 0)",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}),M.element("path",{d:"M501.9574,124.6258V45.4794S504.6829,10,466.5256,10h-80.403",transform:"translate(0 0)",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}),M.element("path",{d:"M387.5279,501.9574h79.04S502,504.6865,502,466.4779v-80.511",transform:"translate(0 0)",fill:"none",stroke:o,"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":n||20}))}}!function qrcode_stroke_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(qrcode_stroke_Icon,"hash","07cbc9451ecfc6e6e5920cf45eb00829");var V=qrcode_stroke_Icon;function _extends(){return(_extends=Object.assign||function(e){for(var t=1;tM.element("p",{class:"x12 fs4 lh12 ls12 "+(t==n-1?"m4t":""),html:e}))))}renderStep({title:e,text:t,link:n,icon:r}){return M.element("div",{class:"md+x4 p1"},M.element("div",{class:"xx bgm2 p8y p4x y12"},M.element(r,{height:40,class:"cm2z m4b"}),M.element("h2",{class:"x12 fs6"},M.element("a",{href:n,title:e,class:"ci1"},e)),M.element("p",{class:"x12 fs4 m4y",html:t})))}renderCycle(){const e=this.renderStep;return M.element("section",{class:"x xx sm-p2x md+bcm2y md+p10y"},M.element(e,_extends({icon:Z},this.i18n.cycle.ssr)),M.element(e,_extends({icon:R},this.i18n.cycle.spa)),M.element(e,_extends({icon:V},this.i18n.cycle.ssg)))}renderAbout(){return M.element("section",{class:"x xx sm-p2x sm-p10y md+p20t md+p10b"},M.element("h2",{class:"x12 sm-fs8 md+fs12 m2b"}," ",this.i18n.about.heading," "),this.i18n.about.taglines.map(e=>M.element("p",{class:"x12 fs4",html:e})))}renderFeature({title:e,key:t,link:n}){return M.element("div",{class:"md-x12 lg+x6 p1"},!!e&&M.element("div",{class:"xsb bcm2 p4"},M.element("h3",{class:"ff2 fw3 fs4"},M.element("a",{href:n,title:e,class:"ci1"},e))),M.element(Q,{key:t}))}renderShowcase(){const e=this.renderFeature;return M.element("section",{class:"x lg-x12z xl md-p2x"},M.element(e,{key:"ProductList"}),M.element(e,{key:"ProductForm"}),M.element("div",{class:"xl x12 p1"},M.element("div",{class:"xl x12 bcm2 p2t"},this.i18n.showcase.descriptions.map(e=>M.element("p",{class:"xx x12 m2b p4x lh16",html:e})))))}renderProductivity(){return M.element("section",{class:"x xx sm-p2x sm-p10y md+p20y"},M.element("h2",{class:"x12 sm-fs8 md+fs12 m2b"}," ",this.i18n.productivity.heading," "),M.element("p",{class:"x12 fs4"}," ",this.i18n.productivity.tagline," "))}renderFeatures(){const e=this.renderFeature;return M.element("section",{class:"x lg-x12z xl lg-p2x"},this.i18n.features.map(t=>M.element(e,t)))}renderVideo({title:e,link:t,thumbnail:n}){return M.element("div",{class:"xx x12 md+x4 p1"},M.element("a",{href:t,title:e,target:"_blank",rel:"noopener"},M.element("img",{src:n,alt:e,height:"209",width:"372",loading:"lazy"})))}renderPlaylist({worker:e}){const t=this.renderVideo;return!!e.online&&M.element("section",{class:"x xx sm-p10t md+p20t sm-p2x"},M.element("h2",{class:"x12 sm-fs8 md+fs12"}," ",this.i18n.playlist.heading," "),M.element("p",{class:"x12 fs4"}," ",this.i18n.playlist.tagline," "),M.element("div",{class:"xl x12 p10t"},this.i18n.playlist.videos.map(e=>M.element(t,e))))}renderReason({title:e,description:t,closer:n,link:r}){return M.element("div",{class:"md+x6 p1"},M.element("div",{class:"xx bgm2 p8y p4x y12"},M.element("h3",{class:"x12 fs6"},M.element("a",{href:r,class:"ci1"},e)),M.element("p",{class:"x12 fs4 m4y"}," ",t," "),M.element("strong",null,n)))}renderWhy(){const e=this.renderReason;return M.element("section",{class:"sm-p2x sm-m10t md+m20t"},M.element("div",{class:"x xx md+bcm2t p10y"},M.element("h2",{class:"x12 sm-fs8 md+fs12"}," ",this.i18n.why.heading," "),M.element("div",{class:"xl p10y"},this.i18n.why.reasons.map(t=>M.element(e,t))),M.element("a",{href:this.i18n.why.getStarted.link,title:this.i18n.why.getStarted.text,class:"bci1 cm1 ci1:h bgi1 bgm1:h p2y p4x"},this.i18n.why.getStarted.text),M.element("span",{class:"x12 fs4"}," ╰(*°▽°*)╯ ")))}render(){const e=this.renderWhy,t=this.renderPlaylist,n=this.renderFeatures,r=this.renderProductivity,i=this.renderShowcase,a=this.renderAbout,s=this.renderCycle,l=this.renderHero;return!!this.i18n&&M.element("div",null,M.element(l,null),M.element(s,null),M.element(a,null),M.element(i,null),M.element(r,null),M.element(n,null),M.element(t,null),M.element(e,null))}}!function Home_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Home_Home,"hash","8717a6a469d15497e539294dd4ea5d4d");var G=Home_Home;class Waifu_Waifu extends N{renderAttribute({label:e,value:t}){return M.element("li",{class:"xl m2b"},M.element("b",null,e),": ",t)}render({worker:e}){const t=this.renderAttribute;return!!this.i18n&&M.element("div",{class:"x md+p20t p10y sm-p2x"},M.element("div",{class:"xx x12"},e.online&&M.element("img",{src:"/waifu.png",alt:"Nulla-Chan",height:"500"}),M.element("div",{class:"md+p10l"},M.element("h1",{class:"xl m14t"}," Nulla ",M.element("span",{class:"ci1"},"-")," Chan "),M.element("p",{class:"xl m8b"}," ",this.i18n.tagline," "),M.element("ul",null,this.i18n.attributes.map(e=>M.element(t,e))),M.element("span",{class:"xl m8t"},this.i18n.artist.label,M.element("a",{href:this.i18n.artist.href,target:"_blank",rel:"noopener",class:"ci1 m2x"}," ",this.i18n.artist.text," ")),M.element("span",{class:"xl m2t"},this.i18n.concept.label,M.element("a",{href:this.i18n.concept.href,target:"_blank",rel:"noopener",class:"ci1 m2x"}," ",this.i18n.concept.text," ")))),M.element("blockquote",{class:"xx x12 m10y"},this.i18n.descriptions.map(e=>M.element("p",{class:"x12"}," ",e," "))))}}!function Waifu_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Waifu_Waifu,"hash","9c72b6bd3886d6c973fffb1317b0396d");var U=Waifu_Waifu;function Contributors_extends(){return(Contributors_extends=Object.assign||function(e){for(var t=1;te));this.packages=[...t].map(t=>e.find(e=>e.login==t))}renderTopic({title:e,paragraphs:t,main:n,children:r}){return M.element("div",{class:"x12 m10b"},M.element("element",{tag:n?"h1":"h2",class:"x12 sm-fs6 md+fs8 m2b"},e),t&&M.element("div",{class:"xl x12"},t.map(e=>M.element("p",{class:"x12 fs4 m1b",html:e}))),M.element("div",{class:"xl x12"},r))}renderState(){const e=this.renderTopic,{state:t}=this.i18n;return M.element(e,Contributors_extends({},t,{main:!0}))}renderRoadmap(){const e=this.renderTopic,{roadmap:t}=this.i18n;return M.element(e,t)}renderCoreContributor({github:e,name:t,role:n,description:r,contribution:i}){return M.element("div",{class:"xl x12 bcm2 p2 m2t"},M.element("img",{class:"xl",src:`https://github.com/${e}.png`,alt:t,width:"90",height:"90",style:"height: 90px"}),M.element("div",{class:"md+x10 md+p3l sm-m3t"},M.element("h3",null,M.element("a",{href:"https://github.com/"+e,target:"_blank",rel:"noopener",class:"ci1"},t)),M.element("h4",{class:"m1y",html:n}),M.element("p",null," ",r," "),M.element("p",null," ",i," ")))}renderCoreTeam(){const e=this.renderCoreContributor,t=this.renderTopic,{core:n}=this.i18n;return M.element(t,n,n.team.map(t=>M.element(e,t)))}renderInstructions(){const e=this.renderTopic,{instructions:t}=this.i18n;return M.element(e,t)}renderContributor({login:e,avatar_url:t,html_url:n}){return M.element("div",{class:"xx sm-x6 bcm2 p2 m2t"},M.element("a",{href:n,title:e,target:"_blank",rel:"noopener",class:"ci1"},M.element("img",{class:"xl",src:t,alt:e,width:"90",height:"90",style:"height: 90px"})))}renderGithubContributors({title:e,key:t}){const n=this.renderContributor,r=this.renderTopic;return M.element(r,{title:e},M.element("div",{class:"xl"},this[t].map(e=>M.element(n,e))),M.element("p",{class:"x12 fs4 m2t"},this.i18n.githubCacheWarning))}render(){const e=this.renderInstructions,t=this.renderGithubContributors,n=this.renderCoreTeam,r=this.renderRoadmap,i=this.renderState;return!!this.i18n&&M.element("section",{class:"x sm-p4x sm-p10y md+p20y"},M.element(i,null),M.element(r,null),M.element(n,null),M.element(t,{title:this.i18n.packages.title,key:"packages"}),M.element(t,{title:this.i18n.documentation.title,key:"documentation"}),M.element(e,null))}}Contributors_defineProperty(Contributors_Contributors,"hash","60db8b7bc944ff27c90efbea342addb5");var K=Contributors_Contributors;class Loader_Loader extends M{render({worker:e}){return!!e.fetching&&M.element("div",{class:"loader-cog z24 pftl xx yy x12 xvw y12 yvh bgm1 op18"},M.element(Z,{animation:"spin",speed:"slow",height:40,class:"cm3"}))}}!function Loader_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Loader_Loader,"hash","169a2e469dab4716aa09babedd4eefb5");var J=Loader_Loader;class GoogleAnalytics_GoogleAnalytics extends M{hydrate({router:e,page:t,id:n}){function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config",n,{page_title:t.title,page_path:e.url}),window.addEventListener(t.event,()=>{gtag("event","page_view",{page_title:t.title,page_path:e.url})})}render({id:e,self:t}){const n="https://www.googletagmanager.com";return t.hydrated?M.element("script",{async:!0,src:`${n}/gtag/js?id=${e}`}):M.element("head",null,M.element("link",{rel:"preconnect",href:n}))}}!function GoogleAnalytics_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(GoogleAnalytics_GoogleAnalytics,"hash","f6eb2002bffbe4d1d528bc45653ff256");var X=GoogleAnalytics_GoogleAnalytics;class Application_Application extends M{renderPreloader(){return M.element("head",null,M.element("link",{rel:"preload",href:"/roboto-v20-latin-300.woff2",as:"font",type:"font/woff2",crossorigin:!0}),M.element("link",{rel:"preload",href:"/roboto-v20-latin-500.woff2",as:"font",type:"font/woff2",crossorigin:!0}),M.element("link",{rel:"preload",href:"/crete-round-v9-latin-regular.woff2",as:"font",type:"font/woff2",crossorigin:!0}))}prepare(e){e.mode="light",e.oppositeMode="dark"}hydrate(e){localStorage.mode&&(e.mode=localStorage.mode,"dark"===e.mode&&(e.oppositeMode="light"))}render({router:e,mode:t}){const n=this.renderPreloader,r=e.url.startsWith("/pt-br")?"pt-BR":"en-US";return M.element("main",{class:t+" bgm1 cm3"},M.element(F,{locale:r}),M.element(G,{route:"/",locale:"en-US"}),M.element(G,{route:"/pt-br",locale:"pt-BR"}),M.element(W,{route:"/documentation",locale:"en-US"}),M.element(W,{route:"/pt-br/documentacao",locale:"pt-BR"}),M.element(D,{route:"/components",locale:"en-US"}),M.element(D,{route:"/pt-br/componentes",locale:"pt-BR"}),M.element(K,{route:"/contributors",locale:"en-US"}),M.element(K,{route:"/pt-br/contribuidores",locale:"pt-BR"}),M.element(U,{route:"/waifu",locale:"en-US"}),M.element(U,{route:"/pt-br/waifu",locale:"pt-BR"}),M.element(B,{route:"/pt-br/:slug",locale:"pt-BR"}),M.element(B,{route:"/:slug",locale:"en-US"}),M.element(X,{id:"G-E7GZ5Z4MLN"}),M.element(n,null),M.element(J,null),M.element(I,{locale:r}))}}!function Application_defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}(Application_Application,"hash","719b00940d423c380a55cfc7340a0008");var Y=Application_Application;M.start(Y)}]); \ No newline at end of file diff --git a/docs/components.html b/docs/components.html deleted file mode 100644 index 6a72f9f1..00000000 --- a/docs/components.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Community Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Community Components

A curated list of Nullstack components made by the community.

If you want to add a component to this list open an issue on github.

- - - \ No newline at end of file diff --git a/docs/components/index.html b/docs/components/index.html deleted file mode 100644 index 6a72f9f1..00000000 --- a/docs/components/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Community Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Community Components

A curated list of Nullstack components made by the community.

If you want to add a component to this list open an issue on github.

- - - \ No newline at end of file diff --git a/docs/components/index.json b/docs/components/index.json deleted file mode 100644 index dd0e4303..00000000 --- a/docs/components/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-5":{"locale":"en-US","i18n":{"title":"Community Components","description":"A curated list of Nullstack components made by the community","heading":"Community Components","tagline":"A curated list of Nullstack components made by the community.","contribute":"If you want to add a component to this list open an issue on github.","topics":[{"title":"Integrations","projects":[{"title":"Google Analytics","repository":"https://github.com/Mortaro/nullstack-google-analytics"},{"title":"Facebook Pixel","repository":"https://github.com/Mortaro/nullstack-facebook-pixel"}]},{"title":"General Inputs","projects":[{"title":"Currency Input","repository":"https://github.com/Mortaro/nullstack-currency-input"},{"title":"Date Input","repository":"https://github.com/Mortaro/nullstack-date-input"},{"title":"CKEditor Adapter","repository":"https://github.com/Mortaro/nullstack-ckeditor-adapter"},{"title":"Upload Input","repository":"https://github.com/Mortaro/nullstack-upload-input"}]},{"title":"Brazilian Inputs","tagline":{"title":"Nullstack is a Brazilian Framework","text":"🤘 Nullstack é BR porr@!"},"projects":[{"title":"CPF and CNPJ Inputs","repository":"https://github.com/Mortaro/nullstack-cpf-cnpj-input"},{"title":"CEP Input","repository":"https://github.com/Mortaro/nullstack-cep-input"},{"title":"Phone Input","repository":"https://github.com/Mortaro/nullstack-phone-input"}]}]}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"priority":0.3,"title":"Community Components - Nullstack","description":"A curated list of Nullstack components made by the community","locale":"en-US"}} \ No newline at end of file diff --git a/docs/context-data.html b/docs/context-data.html deleted file mode 100644 index a06dc5d1..00000000 --- a/docs/context-data.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - Context Data - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Data

    -
  • Type: object
  • -
  • Origin: Component Context
  • -
  • Availability: client
  • -
  • readonly in client context
  • -
-

It gives you information about the element dataset.

-

You can use this key to avoid polluting your DOM with invalid attributes.

-
-

💡 This helps Nullstack set attributes without wasting time validating them.

-
-

Any data-* attributes will receive a respective camelized key on the data object.

-

You can assign data attributes both via data-* and a data key that accepts an object with camelized keys.

-

The kebab version is also available in the context.

-
import Nullstack from 'nullstack';
-
-class ContextData extends Nullstack {
-
-  count = 1;
-
-  calculate({data}) {
-    this.count = this.count * data.multiply + data.sum;
-  }
-
-  renderInner(context) {
-    const {data} = context;
-    return (
-      <div data={data}>
-        {data.frameworkName}
-        is same as
-        {context['data-framework-name']}
-      </div>
-    )
-  }
-  
-  render({data}) {
-    return (
-      <div> 
-        <button onclick={this.calculate} data-multiply={3} data={{sum: 2}}>
-          Calculate
-        </button>
-        <Inner data-framework-name="Nullstack" />
-      </div>
-    )
-  }
-
-}
-
-export default ContextData;
-
-
-

💡 Camelized keys from the data object will result in kebab attributes in the DOM.

-
-

Next step

⚔ Learn about the context environment.

-
- - - \ No newline at end of file diff --git a/docs/context-data/index.html b/docs/context-data/index.html deleted file mode 100644 index a06dc5d1..00000000 --- a/docs/context-data/index.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - Context Data - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Data

    -
  • Type: object
  • -
  • Origin: Component Context
  • -
  • Availability: client
  • -
  • readonly in client context
  • -
-

It gives you information about the element dataset.

-

You can use this key to avoid polluting your DOM with invalid attributes.

-
-

💡 This helps Nullstack set attributes without wasting time validating them.

-
-

Any data-* attributes will receive a respective camelized key on the data object.

-

You can assign data attributes both via data-* and a data key that accepts an object with camelized keys.

-

The kebab version is also available in the context.

-
import Nullstack from 'nullstack';
-
-class ContextData extends Nullstack {
-
-  count = 1;
-
-  calculate({data}) {
-    this.count = this.count * data.multiply + data.sum;
-  }
-
-  renderInner(context) {
-    const {data} = context;
-    return (
-      <div data={data}>
-        {data.frameworkName}
-        is same as
-        {context['data-framework-name']}
-      </div>
-    )
-  }
-  
-  render({data}) {
-    return (
-      <div> 
-        <button onclick={this.calculate} data-multiply={3} data={{sum: 2}}>
-          Calculate
-        </button>
-        <Inner data-framework-name="Nullstack" />
-      </div>
-    )
-  }
-
-}
-
-export default ContextData;
-
-
-

💡 Camelized keys from the data object will result in kebab attributes in the DOM.

-
-

Next step

⚔ Learn about the context environment.

-
- - - \ No newline at end of file diff --git a/docs/context-data/index.json b/docs/context-data/index.json deleted file mode 100644 index 57a8078b..00000000 --- a/docs/context-data/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Data","html":"
    \n
  • Type: object
  • \n
  • Origin: Component Context
  • \n
  • Availability: client
  • \n
  • readonly in client context
  • \n
\n

It gives you information about the element dataset.

\n

You can use this key to avoid polluting your DOM with invalid attributes.

\n
\n

💡 This helps Nullstack set attributes without wasting time validating them.

\n
\n

Any data-* attributes will receive a respective camelized key on the data object.

\n

You can assign data attributes both via data-* and a data key that accepts an object with camelized keys.

\n

The kebab version is also available in the context.

\n
import Nullstack from 'nullstack';\n\nclass ContextData extends Nullstack {\n\n  count = 1;\n\n  calculate({data}) {\n    this.count = this.count * data.multiply + data.sum;\n  }\n\n  renderInner(context) {\n    const {data} = context;\n    return (\n      <div data={data}>\n        {data.frameworkName}\n        is same as\n        {context['data-framework-name']}\n      </div>\n    )\n  }\n  \n  render({data}) {\n    return (\n      <div> \n        <button onclick={this.calculate} data-multiply={3} data={{sum: 2}}>\n          Calculate\n        </button>\n        <Inner data-framework-name=\"Nullstack\" />\n      </div>\n    )\n  }\n\n}\n\nexport default ContextData;\n
\n
\n

💡 Camelized keys from the data object will result in kebab attributes in the DOM.

\n
\n

Next step

⚔ Learn about the context environment.

\n","description":"The data object is a proxy in the Component Context available in client and gives you information about the element dataset"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Data - Nullstack","description":"The data object is a proxy in the Component Context available in client and gives you information about the element dataset"}} \ No newline at end of file diff --git a/docs/context-environment.html b/docs/context-environment.html deleted file mode 100644 index 3fa3e28d..00000000 --- a/docs/context-environment.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Context Environment - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Environment

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readonly in server/client context
  • -
-

It gives you information about the current environment.

-

The following keys are available in the object:

-
    -
  • client: boolean
  • -
  • server: boolean
  • -
  • development: boolean
  • -
  • production: boolean
  • -
  • static: boolean
  • -
  • key: string
  • -
-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
- 
-  render({environment}) {
-    return (
-      <div> 
-        {environment.client && <p>I'm in the client</p>}
-        {environment.server && <p>I'm in the server</p>}
-        {environment.development && <p>I'm in development mode</p>}
-        {environment.production && <p>I'm in production mode</p>}
-        {environment.static && <p>I'm in a static site</p>}
-        <p> My key is {environment.key}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

The environment key is an md5 hash of the current environment folder outputs. The key is appended to assets and static API path to assist cache control.

-

Next step

⚔ Learn about the context page.

-
- - - \ No newline at end of file diff --git a/docs/context-environment/index.html b/docs/context-environment/index.html deleted file mode 100644 index 3fa3e28d..00000000 --- a/docs/context-environment/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Context Environment - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Environment

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readonly in server/client context
  • -
-

It gives you information about the current environment.

-

The following keys are available in the object:

-
    -
  • client: boolean
  • -
  • server: boolean
  • -
  • development: boolean
  • -
  • production: boolean
  • -
  • static: boolean
  • -
  • key: string
  • -
-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
- 
-  render({environment}) {
-    return (
-      <div> 
-        {environment.client && <p>I'm in the client</p>}
-        {environment.server && <p>I'm in the server</p>}
-        {environment.development && <p>I'm in development mode</p>}
-        {environment.production && <p>I'm in production mode</p>}
-        {environment.static && <p>I'm in a static site</p>}
-        <p> My key is {environment.key}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

The environment key is an md5 hash of the current environment folder outputs. The key is appended to assets and static API path to assist cache control.

-

Next step

⚔ Learn about the context page.

-
- - - \ No newline at end of file diff --git a/docs/context-environment/index.json b/docs/context-environment/index.json deleted file mode 100644 index e40818f0..00000000 --- a/docs/context-environment/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Environment","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: server/client
  • \n
  • readonly in server/client context
  • \n
\n

It gives you information about the current environment.

\n

The following keys are available in the object:

\n
    \n
  • client: boolean
  • \n
  • server: boolean
  • \n
  • development: boolean
  • \n
  • production: boolean
  • \n
  • static: boolean
  • \n
  • key: string
  • \n
\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n \n  render({environment}) {\n    return (\n      <div> \n        {environment.client && <p>I'm in the client</p>}\n        {environment.server && <p>I'm in the server</p>}\n        {environment.development && <p>I'm in development mode</p>}\n        {environment.production && <p>I'm in production mode</p>}\n        {environment.static && <p>I'm in a static site</p>}\n        <p> My key is {environment.key}</p>\n      </div>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

The environment key is an md5 hash of the current environment folder outputs. The key is appended to assets and static API path to assist cache control.

\n

Next step

⚔ Learn about the context page.

\n","description":"The environment object is a proxy in the Nullstack Context available in both client and server and gives you information about the current environment"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Environment - Nullstack","description":"The environment object is a proxy in the Nullstack Context available in both client and server and gives you information about the current environment"}} \ No newline at end of file diff --git a/docs/context-page.html b/docs/context-page.html deleted file mode 100644 index e477af0f..00000000 --- a/docs/context-page.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - Context Page - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Page

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in server/client context
  • -
-

It gives you information about the document head metatags.

-

page keys will be used to generate metatags during server-side rendering and must be assigned before initiate while this resolved.

-

The following keys are available in the object:

-
    -
  • title: string
  • -
  • image: string (absolute or relative URL)
  • -
  • description: string
  • -
  • canonical: string (absolute or relative URL)
  • -
  • locale: string
  • -
  • robots: string
  • -
  • schema: object
  • -
  • changes: string
  • -
  • priority: number
  • -
  • status: number
  • -
-

When the title key is assigned on the client-side, the document title will be updated.

-

Nullstack uses the changes and priority keys to generate the sitemap.xml.

-

The sitemap is generated automatically only when using static site generation and must be manually generated in server-side rendered applications.

-

The changes key represents the changefreq key in the sitemap.xml and if assigned must be one of the following values:

-
    -
  • always
  • -
  • hourly
  • -
  • daily
  • -
  • weekly
  • -
  • monthly
  • -
  • yearly
  • -
  • never
  • -
-

The priority key is a number between 0.0 and 1.0 that represents the priority key in the sitemap.xml.

-

Nullstack does not set a default priority, however, sitemaps assume a 0.5 priority when not explicitly set.

-

Besides title and locale all other keys have sensible defaults generated based on the application scope.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  prepare({project, page}) {
-    page.title = `${project.name} - Page Title`;
-    page.image = '/image.jpg';
-    page.description = 'Page meta description';
-    page.canonical = 'http://absolute.url/canonical-link';
-    page.locale = 'pt-BR';
-    page.robots = 'index, follow';
-    page.schema = {};
-    page.changes = 'weekly';
-    page.priority = 1;
-  }
-
-  render({page}) {
-    return (
-      <div>
-        <h1>{page.title}</h1>
-        <p>{page.description}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

Custom Events

Updating page.title will raise a custom event.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({page}) {
-    window.addEventListener(page.event, () => {
-      console.log(`New title: ${page.title}`);
-    });
-  }
-
-}
-
-export default Analytics;
-
-
-

🔥 page.event is only available in client functions/lifecycles.

-
-

Error pages

If during the server-side render process the page.status has any value besides 200, your application will receive another render pass that gives you the chance to adjust the interface according to the status.

-

The status key will be raised with the HTTP response.

-

The page status will be modified to 500 and receive another render pass if the page raise an exception while rendering.

-

The status of server functions responses will be set to the page.status.

-
import Nullstack from 'nullstack';
-import ErrorPage from './ErrorPage';
-import HomePage from './HomePage';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render({page}) {
-    return (
-      <main>
-        {page.status !== 200 && <ErrorPage route="*" />}
-        <HomePage route="/" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 Assigning to the status key during the single-page application mode will have no effect.

-
-

Next step

⚔ Learn about the context project.

-
- - - \ No newline at end of file diff --git a/docs/context-page/index.html b/docs/context-page/index.html deleted file mode 100644 index e477af0f..00000000 --- a/docs/context-page/index.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - Context Page - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Page

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in server/client context
  • -
-

It gives you information about the document head metatags.

-

page keys will be used to generate metatags during server-side rendering and must be assigned before initiate while this resolved.

-

The following keys are available in the object:

-
    -
  • title: string
  • -
  • image: string (absolute or relative URL)
  • -
  • description: string
  • -
  • canonical: string (absolute or relative URL)
  • -
  • locale: string
  • -
  • robots: string
  • -
  • schema: object
  • -
  • changes: string
  • -
  • priority: number
  • -
  • status: number
  • -
-

When the title key is assigned on the client-side, the document title will be updated.

-

Nullstack uses the changes and priority keys to generate the sitemap.xml.

-

The sitemap is generated automatically only when using static site generation and must be manually generated in server-side rendered applications.

-

The changes key represents the changefreq key in the sitemap.xml and if assigned must be one of the following values:

-
    -
  • always
  • -
  • hourly
  • -
  • daily
  • -
  • weekly
  • -
  • monthly
  • -
  • yearly
  • -
  • never
  • -
-

The priority key is a number between 0.0 and 1.0 that represents the priority key in the sitemap.xml.

-

Nullstack does not set a default priority, however, sitemaps assume a 0.5 priority when not explicitly set.

-

Besides title and locale all other keys have sensible defaults generated based on the application scope.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  prepare({project, page}) {
-    page.title = `${project.name} - Page Title`;
-    page.image = '/image.jpg';
-    page.description = 'Page meta description';
-    page.canonical = 'http://absolute.url/canonical-link';
-    page.locale = 'pt-BR';
-    page.robots = 'index, follow';
-    page.schema = {};
-    page.changes = 'weekly';
-    page.priority = 1;
-  }
-
-  render({page}) {
-    return (
-      <div>
-        <h1>{page.title}</h1>
-        <p>{page.description}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

Custom Events

Updating page.title will raise a custom event.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({page}) {
-    window.addEventListener(page.event, () => {
-      console.log(`New title: ${page.title}`);
-    });
-  }
-
-}
-
-export default Analytics;
-
-
-

🔥 page.event is only available in client functions/lifecycles.

-
-

Error pages

If during the server-side render process the page.status has any value besides 200, your application will receive another render pass that gives you the chance to adjust the interface according to the status.

-

The status key will be raised with the HTTP response.

-

The page status will be modified to 500 and receive another render pass if the page raise an exception while rendering.

-

The status of server functions responses will be set to the page.status.

-
import Nullstack from 'nullstack';
-import ErrorPage from './ErrorPage';
-import HomePage from './HomePage';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render({page}) {
-    return (
-      <main>
-        {page.status !== 200 && <ErrorPage route="*" />}
-        <HomePage route="/" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 Assigning to the status key during the single-page application mode will have no effect.

-
-

Next step

⚔ Learn about the context project.

-
- - - \ No newline at end of file diff --git a/docs/context-page/index.json b/docs/context-page/index.json deleted file mode 100644 index 896afaf7..00000000 --- a/docs/context-page/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Page","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: server/client
  • \n
  • readwrite in server/client context
  • \n
\n

It gives you information about the document head metatags.

\n

page keys will be used to generate metatags during server-side rendering and must be assigned before initiate while this resolved.

\n

The following keys are available in the object:

\n
    \n
  • title: string
  • \n
  • image: string (absolute or relative URL)
  • \n
  • description: string
  • \n
  • canonical: string (absolute or relative URL)
  • \n
  • locale: string
  • \n
  • robots: string
  • \n
  • schema: object
  • \n
  • changes: string
  • \n
  • priority: number
  • \n
  • status: number
  • \n
\n

When the title key is assigned on the client-side, the document title will be updated.

\n

Nullstack uses the changes and priority keys to generate the sitemap.xml.

\n

The sitemap is generated automatically only when using static site generation and must be manually generated in server-side rendered applications.

\n

The changes key represents the changefreq key in the sitemap.xml and if assigned must be one of the following values:

\n
    \n
  • always
  • \n
  • hourly
  • \n
  • daily
  • \n
  • weekly
  • \n
  • monthly
  • \n
  • yearly
  • \n
  • never
  • \n
\n

The priority key is a number between 0.0 and 1.0 that represents the priority key in the sitemap.xml.

\n

Nullstack does not set a default priority, however, sitemaps assume a 0.5 priority when not explicitly set.

\n

Besides title and locale all other keys have sensible defaults generated based on the application scope.

\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n\n  prepare({project, page}) {\n    page.title = `${project.name} - Page Title`;\n    page.image = '/image.jpg';\n    page.description = 'Page meta description';\n    page.canonical = 'http://absolute.url/canonical-link';\n    page.locale = 'pt-BR';\n    page.robots = 'index, follow';\n    page.schema = {};\n    page.changes = 'weekly';\n    page.priority = 1;\n  }\n\n  render({page}) {\n    return (\n      <div>\n        <h1>{page.title}</h1>\n        <p>{page.description}</p>\n      </div>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Custom Events

Updating page.title will raise a custom event.

\n
import Nullstack from 'nullstack';\n\nclass Analytics extends Nullstack {\n\n  hydrate({page}) {\n    window.addEventListener(page.event, () => {\n      console.log(`New title: ${page.title}`);\n    });\n  }\n\n}\n\nexport default Analytics;\n
\n
\n

🔥 page.event is only available in client functions/lifecycles.

\n
\n

Error pages

If during the server-side render process the page.status has any value besides 200, your application will receive another render pass that gives you the chance to adjust the interface according to the status.

\n

The status key will be raised with the HTTP response.

\n

The page status will be modified to 500 and receive another render pass if the page raise an exception while rendering.

\n

The status of server functions responses will be set to the page.status.

\n
import Nullstack from 'nullstack';\nimport ErrorPage from './ErrorPage';\nimport HomePage from './HomePage';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render({page}) {\n    return (\n      <main>\n        {page.status !== 200 && <ErrorPage route=\"*\" />}\n        <HomePage route=\"/\" />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n
\n

🔥 Assigning to the status key during the single-page application mode will have no effect.

\n
\n

Next step

⚔ Learn about the context project.

\n","description":"The page object is a proxy in the Nullstack Context available in both client and server and gives you information about the document head metatags"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Page - Nullstack","description":"The page object is a proxy in the Nullstack Context available in both client and server and gives you information about the document head metatags"}} \ No newline at end of file diff --git a/docs/context-project.html b/docs/context-project.html deleted file mode 100644 index 89fea311..00000000 --- a/docs/context-project.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - Context Project - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Project

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in the server context
  • -
  • readonly in the client context
  • -
-

It gives you information about the app manifest and some metatags.

-

project keys will be used to generate metatags during server-side rendering and must be assigned before initiate is resolved.

-

project keys will be used to generate the app manifest and should be set during the application startup.

-

The disallow key will be used to generate the robots.txt and should be set during the application startup.

-

project keys are frozen after the application startup.

-

The following keys are available in the object:

-
    -
  • domain: string
  • -
  • name: string
  • -
  • shortName: string
  • -
  • color: string
  • -
  • backgroundColor: string
  • -
  • type: string
  • -
  • display: string
  • -
  • orientation: string
  • -
  • scope: string
  • -
  • root: string
  • -
  • icons: object
  • -
  • favicon: string (relative or absolute url)
  • -
  • disallow: string array (relative paths)
  • -
  • sitemap: boolean or string (relative or absolute url)
  • -
  • cdn: string (absolute url)
  • -
  • protocol: string (http or https)
  • -
-

Besides domain, name and color all other keys have sensible defaults generated based on the application scope.

-

If you do not declare the icons key, Nullstack will scan any icons with the name following the pattern "icon-[WIDTH]x[HEIGHT].png" in your public folder.

-

If the sitemap key is set to true your robots.txt file will point the sitemap to https://${project.domain}/sitemap.xml.

-

The cdn key will prefix your asset bundles and will be available in the context so you can manually prefix other assets.

-

The protocol key is "http" in development mode and "https" in production mode by default.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({project}) {
-    project.name = 'Nullstack';
-    project.shortName = 'Nullstack';
-    project.domain = 'nullstack.app';
-    project.color = '#d22365';
-    project.backgroundColor = '#d22365';
-    project.type = 'website';
-    project.display = 'standalone';
-    project.orientation = 'portrait';
-    project.scope = '/';
-    project.root = '/';
-    project.icons = {
-      '72': '/icon-72x72.png',
-      '128': '/icon-128x128.png',
-      '512': '/icon-512x512.png'
-    };
-    project.favicon = '/favicon.png';
-    project.disallow = ['/admin'];
-    project.sitemap = true;
-    project.cdn = 'cdn.nullstack.app';
-    project.protocol = 'https';
-  }
-
-  prepare({project, page}) {
-    page.title = project.name;
-  }
-
-}
-
-export default Application;
-
-
-

💡 You can override the automatically generated manifest.json and robots.txt by serving your own file from the public folder

-
-

Next step

⚔ Learn about the context settings.

-
- - - \ No newline at end of file diff --git a/docs/context-project/index.html b/docs/context-project/index.html deleted file mode 100644 index 89fea311..00000000 --- a/docs/context-project/index.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - Context Project - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Project

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in the server context
  • -
  • readonly in the client context
  • -
-

It gives you information about the app manifest and some metatags.

-

project keys will be used to generate metatags during server-side rendering and must be assigned before initiate is resolved.

-

project keys will be used to generate the app manifest and should be set during the application startup.

-

The disallow key will be used to generate the robots.txt and should be set during the application startup.

-

project keys are frozen after the application startup.

-

The following keys are available in the object:

-
    -
  • domain: string
  • -
  • name: string
  • -
  • shortName: string
  • -
  • color: string
  • -
  • backgroundColor: string
  • -
  • type: string
  • -
  • display: string
  • -
  • orientation: string
  • -
  • scope: string
  • -
  • root: string
  • -
  • icons: object
  • -
  • favicon: string (relative or absolute url)
  • -
  • disallow: string array (relative paths)
  • -
  • sitemap: boolean or string (relative or absolute url)
  • -
  • cdn: string (absolute url)
  • -
  • protocol: string (http or https)
  • -
-

Besides domain, name and color all other keys have sensible defaults generated based on the application scope.

-

If you do not declare the icons key, Nullstack will scan any icons with the name following the pattern "icon-[WIDTH]x[HEIGHT].png" in your public folder.

-

If the sitemap key is set to true your robots.txt file will point the sitemap to https://${project.domain}/sitemap.xml.

-

The cdn key will prefix your asset bundles and will be available in the context so you can manually prefix other assets.

-

The protocol key is "http" in development mode and "https" in production mode by default.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({project}) {
-    project.name = 'Nullstack';
-    project.shortName = 'Nullstack';
-    project.domain = 'nullstack.app';
-    project.color = '#d22365';
-    project.backgroundColor = '#d22365';
-    project.type = 'website';
-    project.display = 'standalone';
-    project.orientation = 'portrait';
-    project.scope = '/';
-    project.root = '/';
-    project.icons = {
-      '72': '/icon-72x72.png',
-      '128': '/icon-128x128.png',
-      '512': '/icon-512x512.png'
-    };
-    project.favicon = '/favicon.png';
-    project.disallow = ['/admin'];
-    project.sitemap = true;
-    project.cdn = 'cdn.nullstack.app';
-    project.protocol = 'https';
-  }
-
-  prepare({project, page}) {
-    page.title = project.name;
-  }
-
-}
-
-export default Application;
-
-
-

💡 You can override the automatically generated manifest.json and robots.txt by serving your own file from the public folder

-
-

Next step

⚔ Learn about the context settings.

-
- - - \ No newline at end of file diff --git a/docs/context-project/index.json b/docs/context-project/index.json deleted file mode 100644 index fb0bf1de..00000000 --- a/docs/context-project/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Project","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: server/client
  • \n
  • readwrite in the server context
  • \n
  • readonly in the client context
  • \n
\n

It gives you information about the app manifest and some metatags.

\n

project keys will be used to generate metatags during server-side rendering and must be assigned before initiate is resolved.

\n

project keys will be used to generate the app manifest and should be set during the application startup.

\n

The disallow key will be used to generate the robots.txt and should be set during the application startup.

\n

project keys are frozen after the application startup.

\n

The following keys are available in the object:

\n
    \n
  • domain: string
  • \n
  • name: string
  • \n
  • shortName: string
  • \n
  • color: string
  • \n
  • backgroundColor: string
  • \n
  • type: string
  • \n
  • display: string
  • \n
  • orientation: string
  • \n
  • scope: string
  • \n
  • root: string
  • \n
  • icons: object
  • \n
  • favicon: string (relative or absolute url)
  • \n
  • disallow: string array (relative paths)
  • \n
  • sitemap: boolean or string (relative or absolute url)
  • \n
  • cdn: string (absolute url)
  • \n
  • protocol: string (http or https)
  • \n
\n

Besides domain, name and color all other keys have sensible defaults generated based on the application scope.

\n

If you do not declare the icons key, Nullstack will scan any icons with the name following the pattern "icon-[WIDTH]x[HEIGHT].png" in your public folder.

\n

If the sitemap key is set to true your robots.txt file will point the sitemap to https://${project.domain}/sitemap.xml.

\n

The cdn key will prefix your asset bundles and will be available in the context so you can manually prefix other assets.

\n

The protocol key is "http" in development mode and "https" in production mode by default.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({project}) {\n    project.name = 'Nullstack';\n    project.shortName = 'Nullstack';\n    project.domain = 'nullstack.app';\n    project.color = '#d22365';\n    project.backgroundColor = '#d22365';\n    project.type = 'website';\n    project.display = 'standalone';\n    project.orientation = 'portrait';\n    project.scope = '/';\n    project.root = '/';\n    project.icons = {\n      '72': '/icon-72x72.png',\n      '128': '/icon-128x128.png',\n      '512': '/icon-512x512.png'\n    };\n    project.favicon = '/favicon.png';\n    project.disallow = ['/admin'];\n    project.sitemap = true;\n    project.cdn = 'cdn.nullstack.app';\n    project.protocol = 'https';\n  }\n\n  prepare({project, page}) {\n    page.title = project.name;\n  }\n\n}\n\nexport default Application;\n
\n
\n

💡 You can override the automatically generated manifest.json and robots.txt by serving your own file from the public folder

\n
\n

Next step

⚔ Learn about the context settings.

\n","description":"The project object is a proxy in the Nullstack Context available in both client and server and gives you information about the app manifest and some metatags"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Project - Nullstack","description":"The project object is a proxy in the Nullstack Context available in both client and server and gives you information about the app manifest and some metatags"}} \ No newline at end of file diff --git a/docs/context-secrets.html b/docs/context-secrets.html deleted file mode 100644 index 1f54591d..00000000 --- a/docs/context-secrets.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Context Secrets - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Secrets

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server
  • -
  • readwrite in server context
  • -
-

You can use it to configure your application with private information.

-

secrets keys are frozen after the application startup.

-

The following keys are available in the object:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [anySetting]: any
  • -
-

You can assign keys to development or production keys in order to have different secrets per environment.

-

If you assign a key directly to the secrets object it will be available in both environments.

-

When reading from a key you must read directly from the secrets object and Nullstack will return the best-suited value for that environment.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({secrets}) {
-    secrets.development.privateKey = 'SANDBOX_API_KEY';
-    secrets.production.privateKey = 'PRODUCTION_API_KEY';
-    secrets.endpoint = 'https://domain.com/api';
-  }
-
-  static async fetchFromApi({secrets}) {
-    const response = await fetch(secrets.endpoint, {
-      headers: {
-        Authorization: `Bearer ${secrets.privateKey}`
-      }
-    });
-    return await response.json();
-  }
-
-}
-
-export default Application;
-
-

Any environment key starting with NULLSTACK_SECRETS_ will be mapped to the secrets in that environment.

-
-

🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY will be mapped to secrets.privateKey

-
-

Next step

⚔ Learn about the instance self.

-
- - - \ No newline at end of file diff --git a/docs/context-secrets/index.html b/docs/context-secrets/index.html deleted file mode 100644 index 1f54591d..00000000 --- a/docs/context-secrets/index.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Context Secrets - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Secrets

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server
  • -
  • readwrite in server context
  • -
-

You can use it to configure your application with private information.

-

secrets keys are frozen after the application startup.

-

The following keys are available in the object:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [anySetting]: any
  • -
-

You can assign keys to development or production keys in order to have different secrets per environment.

-

If you assign a key directly to the secrets object it will be available in both environments.

-

When reading from a key you must read directly from the secrets object and Nullstack will return the best-suited value for that environment.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({secrets}) {
-    secrets.development.privateKey = 'SANDBOX_API_KEY';
-    secrets.production.privateKey = 'PRODUCTION_API_KEY';
-    secrets.endpoint = 'https://domain.com/api';
-  }
-
-  static async fetchFromApi({secrets}) {
-    const response = await fetch(secrets.endpoint, {
-      headers: {
-        Authorization: `Bearer ${secrets.privateKey}`
-      }
-    });
-    return await response.json();
-  }
-
-}
-
-export default Application;
-
-

Any environment key starting with NULLSTACK_SECRETS_ will be mapped to the secrets in that environment.

-
-

🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY will be mapped to secrets.privateKey

-
-

Next step

⚔ Learn about the instance self.

-
- - - \ No newline at end of file diff --git a/docs/context-secrets/index.json b/docs/context-secrets/index.json deleted file mode 100644 index d6aec67b..00000000 --- a/docs/context-secrets/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Secrets","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: server
  • \n
  • readwrite in server context
  • \n
\n

You can use it to configure your application with private information.

\n

secrets keys are frozen after the application startup.

\n

The following keys are available in the object:

\n
    \n
  • development: object
  • \n
  • production: object
  • \n
  • [anySetting]: any
  • \n
\n

You can assign keys to development or production keys in order to have different secrets per environment.

\n

If you assign a key directly to the secrets object it will be available in both environments.

\n

When reading from a key you must read directly from the secrets object and Nullstack will return the best-suited value for that environment.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({secrets}) {\n    secrets.development.privateKey = 'SANDBOX_API_KEY';\n    secrets.production.privateKey = 'PRODUCTION_API_KEY';\n    secrets.endpoint = 'https://domain.com/api';\n  }\n\n  static async fetchFromApi({secrets}) {\n    const response = await fetch(secrets.endpoint, {\n      headers: {\n        Authorization: `Bearer ${secrets.privateKey}`\n      }\n    });\n    return await response.json();\n  }\n\n}\n\nexport default Application;\n
\n

Any environment key starting with NULLSTACK_SECRETS_ will be mapped to the secrets in that environment.

\n
\n

🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY will be mapped to secrets.privateKey

\n
\n

Next step

⚔ Learn about the instance self.

\n","description":"The secrets object is a proxy in the Nullstack Context available in server which you can use to configure your application with private information"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Secrets - Nullstack","description":"The secrets object is a proxy in the Nullstack Context available in server which you can use to configure your application with private information"}} \ No newline at end of file diff --git a/docs/context-settings.html b/docs/context-settings.html deleted file mode 100644 index a8e718b3..00000000 --- a/docs/context-settings.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - Context Settings - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Settings

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in server context
  • -
  • readonly in client context
  • -
-

You can use it to configure your application with public information.

-

settings keys are frozen after the application startup.

-

The following keys are available in the object:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [anySetting]: any
  • -
-

You can assign keys to development or production keys in order to have different settings per environment.

-

If you assign a key directly to the settings object it will be available in both environments.

-

When reading from a key you must read directly from the settings object and Nullstack will return the best-suited value for that environment.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({settings}) {
-    settings.development.publicKey = 'SANDBOX_API_KEY';
-    settings.production.publicKey = 'PRODUCTION_API_KEY';
-    settings.endpoint = 'https://domain.com/api';
-  }
-
-  async hydrate({settings}) {
-    const response = await fetch(settings.endpoint, {
-      headers: {
-        Authorization: `Bearer ${settings.publicKey}`
-      }
-    });
-    this.data = await response.json();
-  }
-
-}
-
-export default Application;
-
-

Any environment key starting with NULLSTACK_SETTINGS_ will be mapped to the settings in that environment.

-
-

🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY will be mapped to settings.publicKey

-
-

Next step

⚔ Learn about the context secrets.

-
- - - \ No newline at end of file diff --git a/docs/context-settings/index.html b/docs/context-settings/index.html deleted file mode 100644 index a8e718b3..00000000 --- a/docs/context-settings/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - Context Settings - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Settings

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in server context
  • -
  • readonly in client context
  • -
-

You can use it to configure your application with public information.

-

settings keys are frozen after the application startup.

-

The following keys are available in the object:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [anySetting]: any
  • -
-

You can assign keys to development or production keys in order to have different settings per environment.

-

If you assign a key directly to the settings object it will be available in both environments.

-

When reading from a key you must read directly from the settings object and Nullstack will return the best-suited value for that environment.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({settings}) {
-    settings.development.publicKey = 'SANDBOX_API_KEY';
-    settings.production.publicKey = 'PRODUCTION_API_KEY';
-    settings.endpoint = 'https://domain.com/api';
-  }
-
-  async hydrate({settings}) {
-    const response = await fetch(settings.endpoint, {
-      headers: {
-        Authorization: `Bearer ${settings.publicKey}`
-      }
-    });
-    this.data = await response.json();
-  }
-
-}
-
-export default Application;
-
-

Any environment key starting with NULLSTACK_SETTINGS_ will be mapped to the settings in that environment.

-
-

🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY will be mapped to settings.publicKey

-
-

Next step

⚔ Learn about the context secrets.

-
- - - \ No newline at end of file diff --git a/docs/context-settings/index.json b/docs/context-settings/index.json deleted file mode 100644 index f4464754..00000000 --- a/docs/context-settings/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Settings","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: server/client
  • \n
  • readwrite in server context
  • \n
  • readonly in client context
  • \n
\n

You can use it to configure your application with public information.

\n

settings keys are frozen after the application startup.

\n

The following keys are available in the object:

\n
    \n
  • development: object
  • \n
  • production: object
  • \n
  • [anySetting]: any
  • \n
\n

You can assign keys to development or production keys in order to have different settings per environment.

\n

If you assign a key directly to the settings object it will be available in both environments.

\n

When reading from a key you must read directly from the settings object and Nullstack will return the best-suited value for that environment.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({settings}) {\n    settings.development.publicKey = 'SANDBOX_API_KEY';\n    settings.production.publicKey = 'PRODUCTION_API_KEY';\n    settings.endpoint = 'https://domain.com/api';\n  }\n\n  async hydrate({settings}) {\n    const response = await fetch(settings.endpoint, {\n      headers: {\n        Authorization: `Bearer ${settings.publicKey}`\n      }\n    });\n    this.data = await response.json();\n  }\n\n}\n\nexport default Application;\n
\n

Any environment key starting with NULLSTACK_SETTINGS_ will be mapped to the settings in that environment.

\n
\n

🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY will be mapped to settings.publicKey

\n
\n

Next step

⚔ Learn about the context secrets.

\n","description":"The settings object is a proxy in the Nullstack Context available in both client and server which you can use to configure your application with public information"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Settings - Nullstack","description":"The settings object is a proxy in the Nullstack Context available in both client and server which you can use to configure your application with public information"}} \ No newline at end of file diff --git a/docs/context.html b/docs/context.html deleted file mode 100644 index 028cea2a..00000000 --- a/docs/context.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - Context - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context

Every function in Nullstack receives a context as the argument.

-

There are two contexts, one for the client and another one for the server.

-

The client context lives as long as the browser tab is open.

-

The server context lives as long as the server is running.

-

Both contexts are proxies that merge the keys of 3 objects:

-

1 - Nullstack Context

These are the information that the framework makes available to you by default.

-

The available global keys in both server and client are:

-

The keys available only in server functions are:

-

The available instance client keys are:

-

2 - Application Context

When you set a key to the context it will be available for destructuring at any depth of the application, even the parents of your component or 3rd party applications that mount your component.

-

Updating a key in the context causes the application to re-render automatically.

-

You can think of this as a single concept to replace stores, contexts, services, and reducers at the same time using the dependency injection pattern with vanilla javascript objects instead.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  prepare(context) {
-    context.count = 1;
-  }
-
-  static async updateTotalCount(context) {
-    context.totalCount += context.count;
-  }
-
-  async double(context) {
-    context.count += context.count;
-    await this.updateTotalCount();
-  }
-
-  render({count}) {
-    return (
-      <button onclick={this.double}> {count} </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.totalCount = 0;
-  }
-
-  render({count}) {
-    return (
-      <main>
-        {(!count || count < 10) && <Counter />}
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

3 - Component Context

This one contains the attributes you declare in your tag, including data.

-

If the attribute is declared in a component tag every function of that component will have access to that attribute in its context.

-

If the attribute is declared in a tag that has an event it will be merged into the event function context.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.delta + context.amount;
-  }
-
-  render({count, delta}) {
-    return (
-      <button onclick={this.add} amount={1}>
-        add {delta} to {count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  prepare(context) {
-    context.count = 0;
-  }
-
-  render() {
-    return (
-      <main>
-        <Counter delta={2} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Functions Context

Every function of subclasses of Nullstack is injected with a copy of the instance context merged with its arguments.

-

Arguments are optional, but if declared, must be a single object with keys of your choice.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.amount || 1;
-  }
-
-  prepare(context) {
-    context.count = 0;
-    this.add();            // sums 1
-    this.add({amount: 2}); // sums 2
-  }
-
-  async initiate(context) {
-    console.log(context.count); // 3
-  }
-
-}
-
-export default Counter;
-
-

Next step

⚔ Learn about routes and params.

-
- - - \ No newline at end of file diff --git a/docs/context/index.html b/docs/context/index.html deleted file mode 100644 index 028cea2a..00000000 --- a/docs/context/index.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - Context - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context

Every function in Nullstack receives a context as the argument.

-

There are two contexts, one for the client and another one for the server.

-

The client context lives as long as the browser tab is open.

-

The server context lives as long as the server is running.

-

Both contexts are proxies that merge the keys of 3 objects:

-

1 - Nullstack Context

These are the information that the framework makes available to you by default.

-

The available global keys in both server and client are:

-

The keys available only in server functions are:

-

The available instance client keys are:

-

2 - Application Context

When you set a key to the context it will be available for destructuring at any depth of the application, even the parents of your component or 3rd party applications that mount your component.

-

Updating a key in the context causes the application to re-render automatically.

-

You can think of this as a single concept to replace stores, contexts, services, and reducers at the same time using the dependency injection pattern with vanilla javascript objects instead.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  prepare(context) {
-    context.count = 1;
-  }
-
-  static async updateTotalCount(context) {
-    context.totalCount += context.count;
-  }
-
-  async double(context) {
-    context.count += context.count;
-    await this.updateTotalCount();
-  }
-
-  render({count}) {
-    return (
-      <button onclick={this.double}> {count} </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.totalCount = 0;
-  }
-
-  render({count}) {
-    return (
-      <main>
-        {(!count || count < 10) && <Counter />}
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

3 - Component Context

This one contains the attributes you declare in your tag, including data.

-

If the attribute is declared in a component tag every function of that component will have access to that attribute in its context.

-

If the attribute is declared in a tag that has an event it will be merged into the event function context.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.delta + context.amount;
-  }
-
-  render({count, delta}) {
-    return (
-      <button onclick={this.add} amount={1}>
-        add {delta} to {count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  prepare(context) {
-    context.count = 0;
-  }
-
-  render() {
-    return (
-      <main>
-        <Counter delta={2} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Functions Context

Every function of subclasses of Nullstack is injected with a copy of the instance context merged with its arguments.

-

Arguments are optional, but if declared, must be a single object with keys of your choice.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.amount || 1;
-  }
-
-  prepare(context) {
-    context.count = 0;
-    this.add();            // sums 1
-    this.add({amount: 2}); // sums 2
-  }
-
-  async initiate(context) {
-    console.log(context.count); // 3
-  }
-
-}
-
-export default Counter;
-
-

Next step

⚔ Learn about routes and params.

-
- - - \ No newline at end of file diff --git a/docs/context/index.json b/docs/context/index.json deleted file mode 100644 index 95e28c66..00000000 --- a/docs/context/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context","html":"

Every function in Nullstack receives a context as the argument.

\n

There are two contexts, one for the client and another one for the server.

\n

The client context lives as long as the browser tab is open.

\n

The server context lives as long as the server is running.

\n

Both contexts are proxies that merge the keys of 3 objects:

\n

1 - Nullstack Context

These are the information that the framework makes available to you by default.

\n

The available global keys in both server and client are:

\n

The keys available only in server functions are:

\n

The available instance client keys are:

\n

2 - Application Context

When you set a key to the context it will be available for destructuring at any depth of the application, even the parents of your component or 3rd party applications that mount your component.

\n

Updating a key in the context causes the application to re-render automatically.

\n

You can think of this as a single concept to replace stores, contexts, services, and reducers at the same time using the dependency injection pattern with vanilla javascript objects instead.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  prepare(context) {\n    context.count = 1;\n  }\n\n  static async updateTotalCount(context) {\n    context.totalCount += context.count;\n  }\n\n  async double(context) {\n    context.count += context.count;\n    await this.updateTotalCount();\n  }\n\n  render({count}) {\n    return (\n      <button onclick={this.double}> {count} </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    context.totalCount = 0;\n  }\n\n  render({count}) {\n    return (\n      <main>\n        {(!count || count < 10) && <Counter />}\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

3 - Component Context

This one contains the attributes you declare in your tag, including data.

\n

If the attribute is declared in a component tag every function of that component will have access to that attribute in its context.

\n

If the attribute is declared in a tag that has an event it will be merged into the event function context.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  add(context) {\n    context.count += context.delta + context.amount;\n  }\n\n  render({count, delta}) {\n    return (\n      <button onclick={this.add} amount={1}>\n        add {delta} to {count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  prepare(context) {\n    context.count = 0;\n  }\n\n  render() {\n    return (\n      <main>\n        <Counter delta={2} />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Functions Context

Every function of subclasses of Nullstack is injected with a copy of the instance context merged with its arguments.

\n

Arguments are optional, but if declared, must be a single object with keys of your choice.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  add(context) {\n    context.count += context.amount || 1;\n  }\n\n  prepare(context) {\n    context.count = 0;\n    this.add();            // sums 1\n    this.add({amount: 2}); // sums 2\n  }\n\n  async initiate(context) {\n    console.log(context.count); // 3\n  }\n\n}\n\nexport default Counter;\n
\n

Next step

⚔ Learn about routes and params.

\n","description":"Every function in Nullstack receives a context as the argument."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context - Nullstack","description":"Every function in Nullstack receives a context as the argument."}} \ No newline at end of file diff --git a/docs/contexto-page.html b/docs/contexto-page.html deleted file mode 100644 index 3f813663..00000000 --- a/docs/contexto-page.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Page Not Found - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Page Not Found

- - - \ No newline at end of file diff --git a/docs/contexto-page/index.html b/docs/contexto-page/index.html deleted file mode 100644 index 3f813663..00000000 --- a/docs/contexto-page/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Page Not Found - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Page Not Found

- - - \ No newline at end of file diff --git a/docs/contexto-page/index.json b/docs/contexto-page/index.json deleted file mode 100644 index 3758ada4..00000000 --- a/docs/contexto-page/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Page Not Found","html":"

Perhaps you want to learn about how to make a 404 page with Nullstack?

\n

If you are looking for something else, you should read the documentation.

\n","description":"Sorry, this is not the page you are looking for.","status":404},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":404,"title":"Page Not Found - Nullstack","description":"Sorry, this is not the page you are looking for."}} \ No newline at end of file diff --git a/docs/contributors.html b/docs/contributors.html deleted file mode 100644 index ff359e84..00000000 --- a/docs/contributors.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Contributors - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

The State of Nullstack

Nullstack is being developed since January 2019 with features being extracted from freelancing projects.

At this point the API is stable, lifecycle methods and context keys will pretty much be frozen.

We are not yet on 1.0 but really close, the only thing missing is to test it on applications made outside the core team to figure out if it fits the needs of other programmers.

The Roadmap

The next updates will be guided towards fixing any bugs that are found and focus on quality of life.

The updates listed on Nullstack issues are the next planned steps without any particular order.

The Core Team

Nullstack was developed by full-stack neuro-atypical freelancers.

With a heavy background in Rails, Ember.js, React.js and the Vue.js philosophy the inspirations took from those projects might be obvious.

Christian Mortaro

Christian Mortaro

Autistic Author

Creator of the concept. Comes with new API proposals to its favorite rubber ducks and returns with commits.

Reverse engineered wishful thinking code into existence and then refactored it into a framework.

Dayson Marx

Dayson Marx

Distracted Designer

Rubber duck with human skills that makes sure the code is not going too far outside the box, then makes the box look nice.

API reviewer that developed third party projects to test proof of concepts from a front-end focused perspective.

Anny Figueira

Anny Figueira

Autistic Adopter

Rubber duck with a neck to find inconsistencies and problems, waiting till an API is approved to force us into rewriting everything.

An early adopter of the framework that developed real production applications to validate how the parts fit together.

Bianca Augusta

Bianca Augusta

Autistic Artist

Freelance illustrator for 10 years. Warcraft addict, aspiring cosplayer and druid tanker in WoW.

Mother of Nulla-Chan and reads scripts here and there under pure pressure from Mortaro.

Guilherme Correia

Guilherme Correia

import Member from vuejs-br

Experimentalist, universes writer, dreamer and developer when finds and plays the right untitled cassette tape.

User of undocumented features and creator of issues requiring documentation that he will do himself.

Alisson Suassuna

Alisson Suassuna

God's servant

TipsCode instructor. Full-stack JavaScript developer, passionate about technology and servant of the Lord Jesus Christ.

In charge of creating content about Nullstack, classes, tips and tutorials. Focused in making Nullstack easy to use.

Packages Contributors

* The list might take a while to update due to GitHub API cache

Documentation Contributors

* The list might take a while to update due to GitHub API cache

How to Contribute

It's simple. Found a bug or want a new feature?

Create an issue or submit a pull request with tests.

- - - \ No newline at end of file diff --git a/docs/contributors/index.html b/docs/contributors/index.html deleted file mode 100644 index ff359e84..00000000 --- a/docs/contributors/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Contributors - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

The State of Nullstack

Nullstack is being developed since January 2019 with features being extracted from freelancing projects.

At this point the API is stable, lifecycle methods and context keys will pretty much be frozen.

We are not yet on 1.0 but really close, the only thing missing is to test it on applications made outside the core team to figure out if it fits the needs of other programmers.

The Roadmap

The next updates will be guided towards fixing any bugs that are found and focus on quality of life.

The updates listed on Nullstack issues are the next planned steps without any particular order.

The Core Team

Nullstack was developed by full-stack neuro-atypical freelancers.

With a heavy background in Rails, Ember.js, React.js and the Vue.js philosophy the inspirations took from those projects might be obvious.

Christian Mortaro

Christian Mortaro

Autistic Author

Creator of the concept. Comes with new API proposals to its favorite rubber ducks and returns with commits.

Reverse engineered wishful thinking code into existence and then refactored it into a framework.

Dayson Marx

Dayson Marx

Distracted Designer

Rubber duck with human skills that makes sure the code is not going too far outside the box, then makes the box look nice.

API reviewer that developed third party projects to test proof of concepts from a front-end focused perspective.

Anny Figueira

Anny Figueira

Autistic Adopter

Rubber duck with a neck to find inconsistencies and problems, waiting till an API is approved to force us into rewriting everything.

An early adopter of the framework that developed real production applications to validate how the parts fit together.

Bianca Augusta

Bianca Augusta

Autistic Artist

Freelance illustrator for 10 years. Warcraft addict, aspiring cosplayer and druid tanker in WoW.

Mother of Nulla-Chan and reads scripts here and there under pure pressure from Mortaro.

Guilherme Correia

Guilherme Correia

import Member from vuejs-br

Experimentalist, universes writer, dreamer and developer when finds and plays the right untitled cassette tape.

User of undocumented features and creator of issues requiring documentation that he will do himself.

Alisson Suassuna

Alisson Suassuna

God's servant

TipsCode instructor. Full-stack JavaScript developer, passionate about technology and servant of the Lord Jesus Christ.

In charge of creating content about Nullstack, classes, tips and tutorials. Focused in making Nullstack easy to use.

Packages Contributors

* The list might take a while to update due to GitHub API cache

Documentation Contributors

* The list might take a while to update due to GitHub API cache

How to Contribute

It's simple. Found a bug or want a new feature?

Create an issue or submit a pull request with tests.

- - - \ No newline at end of file diff --git a/docs/contributors/index.json b/docs/contributors/index.json deleted file mode 100644 index b33c8133..00000000 --- a/docs/contributors/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-7":{"documentation":[],"packages":[],"locale":"en-US","i18n":{"title":"Contributors","description":"Found a bug or want a new feature? Become a contributor!","state":{"title":"The State of Nullstack","paragraphs":["Nullstack is being developed since January 2019 with features being extracted from freelancing projects.","At this point the API is stable, lifecycle methods and context keys will pretty much be frozen.","We are not yet on 1.0 but really close, the only thing missing is to test it on applications made outside the core team to figure out if it fits the needs of other programmers."]},"roadmap":{"title":"The Roadmap","paragraphs":["The next updates will be guided towards fixing any bugs that are found and focus on quality of life.","The updates listed on Nullstack issues are the next planned steps without any particular order."]},"core":{"title":"The Core Team","paragraphs":["Nullstack was developed by full-stack neuro-atypical freelancers.","With a heavy background in Rails, Ember.js, React.js and the Vue.js philosophy the inspirations took from those projects might be obvious."],"team":[{"name":"Christian Mortaro","role":"Autistic Author","github":"Mortaro","description":"Creator of the concept. Comes with new API proposals to its favorite rubber ducks and returns with commits.","contribution":"Reverse engineered wishful thinking code into existence and then refactored it into a framework."},{"name":"Dayson Marx","role":"Distracted Designer","github":"daysonmarx","description":"Rubber duck with human skills that makes sure the code is not going too far outside the box, then makes the box look nice.","contribution":"API reviewer that developed third party projects to test proof of concepts from a front-end focused perspective."},{"name":"Anny Figueira","role":"Autistic Adopter","github":"AnnyFigueira","description":"Rubber duck with a neck to find inconsistencies and problems, waiting till an API is approved to force us into rewriting everything.","contribution":"An early adopter of the framework that developed real production applications to validate how the parts fit together."},{"name":"Bianca Augusta","role":"Autistic Artist","github":"Bilkaya","description":"Freelance illustrator for 10 years. Warcraft addict, aspiring cosplayer and druid tanker in WoW.","contribution":"Mother of Nulla-Chan and reads scripts here and there under pure pressure from Mortaro."},{"name":"Guilherme Correia","role":"import Member from vuejs-br","github":"GuiDevloper","description":"Experimentalist, universes writer, dreamer and developer when finds and plays the right untitled cassette tape.","contribution":"User of undocumented features and creator of issues requiring documentation that he will do himself."},{"name":"Alisson Suassuna","role":"God's servant","github":"alissonsuassuna","description":"TipsCode instructor. Full-stack JavaScript developer, passionate about technology and servant of the Lord Jesus Christ.","contribution":"In charge of creating content about Nullstack, classes, tips and tutorials. Focused in making Nullstack easy to use."}]},"packages":{"title":"Packages Contributors"},"documentation":{"title":"Documentation Contributors"},"instructions":{"title":"How to Contribute","paragraphs":["It's simple. Found a bug or want a new feature?","Create an issue or submit a pull request with tests."]},"githubCacheWarning":"* The list might take a while to update due to GitHub API cache"}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contributors - Nullstack","description":"Found a bug or want a new feature? Become a contributor!","locale":"en-US"}} \ No newline at end of file diff --git a/docs/crete-round-v9-latin-regular.woff2 b/docs/crete-round-v9-latin-regular.woff2 deleted file mode 100644 index 54ef1dc7..00000000 Binary files a/docs/crete-round-v9-latin-regular.woff2 and /dev/null differ diff --git a/docs/documentation.html b/docs/documentation.html deleted file mode 100644 index 1842d873..00000000 --- a/docs/documentation.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Documentation - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/documentation/index.html b/docs/documentation/index.html deleted file mode 100644 index 1842d873..00000000 --- a/docs/documentation/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Documentation - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/documentation/index.json b/docs/documentation/index.json deleted file mode 100644 index 2e02249e..00000000 --- a/docs/documentation/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-3":{"locale":"en-US","i18n":{"title":"Documentation","description":"Follow these steps and become a full-stack javascript developer!","heading":"Nullstack Documentation","tagline":"Follow these steps and become a full-stack javascript developer!","topics":[{"title":"Core concepts","description":"Start your journey in Nullstack with these basic concepts","links":[{"title":"Getting started","href":"/getting-started"},{"title":"Renderable components","href":"/renderable-components"},{"title":"Stateful components","href":"/stateful-components"},{"title":"Full-stack lifecycle","href":"/full-stack-lifecycle"},{"title":"Server functions","href":"/server-functions"},{"title":"Context","href":"/context"},{"title":"Routes and params","href":"/routes-and-params"},{"title":"Two-way bindings","href":"/two-way-bindings"}]},{"title":"Advanced concepts","description":"These are concepts that you will most likely learn as you need in your projects","links":[{"title":"Application Startup","href":"/application-startup"},{"title":"Context data","href":"/context-data"},{"title":"Context environment","href":"/context-environment"},{"title":"Context page","href":"/context-page"},{"title":"Context project","href":"/context-project"},{"title":"Context settings","href":"/context-settings"},{"title":"Context secrets","href":"/context-secrets"},{"title":"Instance self","href":"/instance-self"},{"title":"Server request and response","href":"/server-request-and-response"},{"title":"Styles","href":"/styles"},{"title":"NJS file extension","href":"/njs-file-extension"},{"title":"Server-side rendering","href":"/server-side-rendering"},{"title":"Static site generation","href":"/static-site-generation"},{"title":"Service Worker","href":"/service-worker"},{"title":"How to deploy a Nullstack application","href":"/how-to-deploy-a-nullstack-application"}]},{"title":"Examples","description":"The best way to learn Nullstack is by reading some code","links":[{"title":"How to use MongoDB with Nullstack","href":"/how-to-use-mongodb-with-nullstack"},{"title":"How to use Google Analytics with Nullstack","href":"/how-to-use-google-analytics-with-nullstack"},{"title":"How to use Facebook Pixel with Nullstack","href":"/how-to-use-facebook-pixel-with-nullstack"}]}]}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"priority":0.8,"title":"Documentation - Nullstack","description":"Follow these steps and become a full-stack javascript developer!","locale":"en-US"}} \ No newline at end of file diff --git a/docs/favicon-96x96.png b/docs/favicon-96x96.png deleted file mode 100644 index a2cec666..00000000 Binary files a/docs/favicon-96x96.png and /dev/null differ diff --git a/docs/full-stack-lifecycle.html b/docs/full-stack-lifecycle.html deleted file mode 100644 index 10ebfd63..00000000 --- a/docs/full-stack-lifecycle.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - Full-Stack Lifecycle - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Full-Stack Lifecycle

Lifecycle methods are special named functions that you can declare in the class.

-

Each lifecycle method runs in a specific order in a queue so it's guaranteed that all components initiated in that cycle will be prepared before the first one is initiated.

-

Prepare

This method is blocking and runs before the first time the component is rendered.

-

You can use this function to set the state that the user will see before things are loaded.

-

If the user is entering from this route prepare will run in the server before Nullstack server-side renders your application.

-

If the user is navigating from another route this method will run in the client.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  prepare() {
-    this.date = new Date();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Initiate

This method can be async and runs right after the component is prepared and rendered for the first time.

-

You can use this function to invoke another server function and load the data to present the page.

-

If the user is entering from this route initiate will run in the server.

-

Nullstack will wait till the promise is resolved and then finally generate the HTML that will be served.

-

If the user is navigating from another route this method will run in the client.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.task = await getTaskByDay({
-      day: this.date
-    });
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Learn more about server functions.

-
-

Hydrate

This method is async and will only run in the client.

-

This method will always run no matter which environment started the component.

-

This is a good place to trigger dependencies that manipulate the dom or can only run on the client-side.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async hydrate() {
-    this.timer = setInterval(() => {
-      console.log(this.date);
-    }, 1000);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Update

This method is async and will only run in the client.

-

This method runs on every component anytime the application state changes.

-
-

🔥 Be careful not to cause infinite loopings when mutating state inside update.

-
-

This will run right before rendering but will not block the rendering queue.

-

The update function will not start running until the application is rendered after the initiate.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async update() {
-    const today = new Date();
-    if(today.getDay() != this.date.getDay()) {
-      this.date = today;
-      await this.initiate();
-    }
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Lifecycle methods have no special side effects, you can call them manually without causing problems.

-
-

Terminate

This method is async and will only run in the client.

-

This method will run after your component leaves the DOM.

-

This is the place to clean up whatever you set up in the hydrate method.

-

The instance will be garbage collected after the Promise is resolved.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async terminate() {
-    clearInterval(this.timer);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Next steps

⚔ Learn about server functions.

-
- - - \ No newline at end of file diff --git a/docs/full-stack-lifecycle/index.html b/docs/full-stack-lifecycle/index.html deleted file mode 100644 index 10ebfd63..00000000 --- a/docs/full-stack-lifecycle/index.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - Full-Stack Lifecycle - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Full-Stack Lifecycle

Lifecycle methods are special named functions that you can declare in the class.

-

Each lifecycle method runs in a specific order in a queue so it's guaranteed that all components initiated in that cycle will be prepared before the first one is initiated.

-

Prepare

This method is blocking and runs before the first time the component is rendered.

-

You can use this function to set the state that the user will see before things are loaded.

-

If the user is entering from this route prepare will run in the server before Nullstack server-side renders your application.

-

If the user is navigating from another route this method will run in the client.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  prepare() {
-    this.date = new Date();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Initiate

This method can be async and runs right after the component is prepared and rendered for the first time.

-

You can use this function to invoke another server function and load the data to present the page.

-

If the user is entering from this route initiate will run in the server.

-

Nullstack will wait till the promise is resolved and then finally generate the HTML that will be served.

-

If the user is navigating from another route this method will run in the client.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.task = await getTaskByDay({
-      day: this.date
-    });
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Learn more about server functions.

-
-

Hydrate

This method is async and will only run in the client.

-

This method will always run no matter which environment started the component.

-

This is a good place to trigger dependencies that manipulate the dom or can only run on the client-side.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async hydrate() {
-    this.timer = setInterval(() => {
-      console.log(this.date);
-    }, 1000);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Update

This method is async and will only run in the client.

-

This method runs on every component anytime the application state changes.

-
-

🔥 Be careful not to cause infinite loopings when mutating state inside update.

-
-

This will run right before rendering but will not block the rendering queue.

-

The update function will not start running until the application is rendered after the initiate.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async update() {
-    const today = new Date();
-    if(today.getDay() != this.date.getDay()) {
-      this.date = today;
-      await this.initiate();
-    }
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Lifecycle methods have no special side effects, you can call them manually without causing problems.

-
-

Terminate

This method is async and will only run in the client.

-

This method will run after your component leaves the DOM.

-

This is the place to clean up whatever you set up in the hydrate method.

-

The instance will be garbage collected after the Promise is resolved.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async terminate() {
-    clearInterval(this.timer);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Next steps

⚔ Learn about server functions.

-
- - - \ No newline at end of file diff --git a/docs/full-stack-lifecycle/index.json b/docs/full-stack-lifecycle/index.json deleted file mode 100644 index 8a0679fa..00000000 --- a/docs/full-stack-lifecycle/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Full-Stack Lifecycle","html":"

Lifecycle methods are special named functions that you can declare in the class.

\n

Each lifecycle method runs in a specific order in a queue so it's guaranteed that all components initiated in that cycle will be prepared before the first one is initiated.

\n

Prepare

This method is blocking and runs before the first time the component is rendered.

\n

You can use this function to set the state that the user will see before things are loaded.

\n

If the user is entering from this route prepare will run in the server before Nullstack server-side renders your application.

\n

If the user is navigating from another route this method will run in the client.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  prepare() {\n    this.date = new Date();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Initiate

This method can be async and runs right after the component is prepared and rendered for the first time.

\n

You can use this function to invoke another server function and load the data to present the page.

\n

If the user is entering from this route initiate will run in the server.

\n

Nullstack will wait till the promise is resolved and then finally generate the HTML that will be served.

\n

If the user is navigating from another route this method will run in the client.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.task = await getTaskByDay({\n      day: this.date\n    });\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

✨ Learn more about server functions.

\n
\n

Hydrate

This method is async and will only run in the client.

\n

This method will always run no matter which environment started the component.

\n

This is a good place to trigger dependencies that manipulate the dom or can only run on the client-side.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async hydrate() {\n    this.timer = setInterval(() => {\n      console.log(this.date);\n    }, 1000);\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Update

This method is async and will only run in the client.

\n

This method runs on every component anytime the application state changes.

\n
\n

🔥 Be careful not to cause infinite loopings when mutating state inside update.

\n
\n

This will run right before rendering but will not block the rendering queue.

\n

The update function will not start running until the application is rendered after the initiate.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async update() {\n    const today = new Date();\n    if(today.getDay() != this.date.getDay()) {\n      this.date = today;\n      await this.initiate();\n    }\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

✨ Lifecycle methods have no special side effects, you can call them manually without causing problems.

\n
\n

Terminate

This method is async and will only run in the client.

\n

This method will run after your component leaves the DOM.

\n

This is the place to clean up whatever you set up in the hydrate method.

\n

The instance will be garbage collected after the Promise is resolved.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async terminate() {\n    clearInterval(this.timer);\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Next steps

⚔ Learn about server functions.

\n","description":"Lifecycle methods are special named functions that you can declare in the class."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Full-Stack Lifecycle - Nullstack","description":"Lifecycle methods are special named functions that you can declare in the class."}} \ No newline at end of file diff --git a/docs/getting-started.html b/docs/getting-started.html deleted file mode 100644 index cc9e6d3f..00000000 --- a/docs/getting-started.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - Getting Started - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Getting Started

-

📌 You can watch a video tutorial on our Youtube Channel.

-
-

Create full-stack javascript applications within seconds using npx to generate your project files from the latest template.

-
-

🔥 The minimum required node.js version for development mode is 12.12.0.

-
-
-

⚠ If the directory you are in contains spaces, you use Windows and npx gives errors, read about the known npx bug.

-
-

Replace project-name with your project name and run the command below to start a project:

-
npx create-nullstack-app project-name
-
-

Change directory to the generated folder:

-
cd project-name
-
-

Install the dependencies:

-
npm install
-
-

Start the application in development mode:

-
npm start
-
-

Understanding the generated files

The following folders and files will be generated:

-

index.js

This is the Webpack entry point.

-

Usually, you don't have to touch this file, but it is a convenient place to import global dependencies like CSS frameworks.

-

src/

This folder will contain the actual source code of your application.

-

src/Application.njs

This is your application main file.

-
-

✨ Learn more about the njs file extension.

-
-

The start function will be automatically called once when you run npm start, use it to populate your server context with things like database, settings, and secrets.

-
-

✨ Learn more about the application startup.

-
-

src/Application.scss

This is an empty file just to demonstrate that you can use SCSS with Nullstack.

-

It is a good practice to import a style file in a component with the same name.

-
-

✨ Learn more about styles.

-
-

public/

Every file in here will be available to anyone from the domain root.

-

By default create-nullstack-app generates the icons required for your manifest.json and images for OG meta tags.

-
-

✨ Learn more about manifest.json.

-
-

Be sure to replace these images with your project identity.

-

.development/

This is the compiled result of your application in development mode.

-
-

🔥 Do not touch this folder

-
-

.production/

This is the compiled result of your application in production mode.

-
-

🔥 Do not touch this folder

-
-
-

✨ Learn more about how to deploy a Nullstack application.

-
-

The known npx bug

Warned on npx issues like #100, #110 and #143, it has an error when trying to resolve the path to his cache folder when contains spaces.

-

If this happens to you, our recommendations are:

-
    -
  • Using downloaded as you normally would with npm:

    -
    npm i -g create-nullstack-app
    -create-nullstack-app project-name
    -
  • -
  • or, change the cache folder directory, as stated here and here:

    -
      -
    • If you want to keep the use of space, replace FirstName with the one used on your path and run:
    • -
    -
    npm config set cache "C:\Users\FirstName~1\AppData\Roaming\npm-cache" --global
    -
    -
      -
    • or, using another path without spaces:
    • -
    -
    npm config set cache C:\tmp\nodejs\npm-cache --global
    -
  • -
-

Next step

⚔ Create your first renderable component.

-
- - - \ No newline at end of file diff --git a/docs/getting-started/index.html b/docs/getting-started/index.html deleted file mode 100644 index cc9e6d3f..00000000 --- a/docs/getting-started/index.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - Getting Started - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Getting Started

-

📌 You can watch a video tutorial on our Youtube Channel.

-
-

Create full-stack javascript applications within seconds using npx to generate your project files from the latest template.

-
-

🔥 The minimum required node.js version for development mode is 12.12.0.

-
-
-

⚠ If the directory you are in contains spaces, you use Windows and npx gives errors, read about the known npx bug.

-
-

Replace project-name with your project name and run the command below to start a project:

-
npx create-nullstack-app project-name
-
-

Change directory to the generated folder:

-
cd project-name
-
-

Install the dependencies:

-
npm install
-
-

Start the application in development mode:

-
npm start
-
-

Understanding the generated files

The following folders and files will be generated:

-

index.js

This is the Webpack entry point.

-

Usually, you don't have to touch this file, but it is a convenient place to import global dependencies like CSS frameworks.

-

src/

This folder will contain the actual source code of your application.

-

src/Application.njs

This is your application main file.

-
-

✨ Learn more about the njs file extension.

-
-

The start function will be automatically called once when you run npm start, use it to populate your server context with things like database, settings, and secrets.

-
-

✨ Learn more about the application startup.

-
-

src/Application.scss

This is an empty file just to demonstrate that you can use SCSS with Nullstack.

-

It is a good practice to import a style file in a component with the same name.

-
-

✨ Learn more about styles.

-
-

public/

Every file in here will be available to anyone from the domain root.

-

By default create-nullstack-app generates the icons required for your manifest.json and images for OG meta tags.

-
-

✨ Learn more about manifest.json.

-
-

Be sure to replace these images with your project identity.

-

.development/

This is the compiled result of your application in development mode.

-
-

🔥 Do not touch this folder

-
-

.production/

This is the compiled result of your application in production mode.

-
-

🔥 Do not touch this folder

-
-
-

✨ Learn more about how to deploy a Nullstack application.

-
-

The known npx bug

Warned on npx issues like #100, #110 and #143, it has an error when trying to resolve the path to his cache folder when contains spaces.

-

If this happens to you, our recommendations are:

-
    -
  • Using downloaded as you normally would with npm:

    -
    npm i -g create-nullstack-app
    -create-nullstack-app project-name
    -
  • -
  • or, change the cache folder directory, as stated here and here:

    -
      -
    • If you want to keep the use of space, replace FirstName with the one used on your path and run:
    • -
    -
    npm config set cache "C:\Users\FirstName~1\AppData\Roaming\npm-cache" --global
    -
    -
      -
    • or, using another path without spaces:
    • -
    -
    npm config set cache C:\tmp\nodejs\npm-cache --global
    -
  • -
-

Next step

⚔ Create your first renderable component.

-
- - - \ No newline at end of file diff --git a/docs/getting-started/index.json b/docs/getting-started/index.json deleted file mode 100644 index ca6d04a0..00000000 --- a/docs/getting-started/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Getting Started","html":"
\n

📌 You can watch a video tutorial on our Youtube Channel.

\n
\n

Create full-stack javascript applications within seconds using npx to generate your project files from the latest template.

\n
\n

🔥 The minimum required node.js version for development mode is 12.12.0.

\n
\n
\n

⚠ If the directory you are in contains spaces, you use Windows and npx gives errors, read about the known npx bug.

\n
\n

Replace project-name with your project name and run the command below to start a project:

\n
npx create-nullstack-app project-name\n
\n

Change directory to the generated folder:

\n
cd project-name\n
\n

Install the dependencies:

\n
npm install\n
\n

Start the application in development mode:

\n
npm start\n
\n

Understanding the generated files

The following folders and files will be generated:

\n

index.js

This is the Webpack entry point.

\n

Usually, you don't have to touch this file, but it is a convenient place to import global dependencies like CSS frameworks.

\n

src/

This folder will contain the actual source code of your application.

\n

src/Application.njs

This is your application main file.

\n
\n

✨ Learn more about the njs file extension.

\n
\n

The start function will be automatically called once when you run npm start, use it to populate your server context with things like database, settings, and secrets.

\n
\n

✨ Learn more about the application startup.

\n
\n

src/Application.scss

This is an empty file just to demonstrate that you can use SCSS with Nullstack.

\n

It is a good practice to import a style file in a component with the same name.

\n
\n

✨ Learn more about styles.

\n
\n

public/

Every file in here will be available to anyone from the domain root.

\n

By default create-nullstack-app generates the icons required for your manifest.json and images for OG meta tags.

\n
\n

✨ Learn more about manifest.json.

\n
\n

Be sure to replace these images with your project identity.

\n

.development/

This is the compiled result of your application in development mode.

\n
\n

🔥 Do not touch this folder

\n
\n

.production/

This is the compiled result of your application in production mode.

\n
\n

🔥 Do not touch this folder

\n
\n
\n

✨ Learn more about how to deploy a Nullstack application.

\n
\n

The known npx bug

Warned on npx issues like #100, #110 and #143, it has an error when trying to resolve the path to his cache folder when contains spaces.

\n

If this happens to you, our recommendations are:

\n
    \n
  • Using downloaded as you normally would with npm:

    \n
    npm i -g create-nullstack-app\ncreate-nullstack-app project-name\n
  • \n
  • or, change the cache folder directory, as stated here and here:

    \n
      \n
    • If you want to keep the use of space, replace FirstName with the one used on your path and run:
    • \n
    \n
    npm config set cache \"C:\\Users\\FirstName~1\\AppData\\Roaming\\npm-cache\" --global\n
    \n
      \n
    • or, using another path without spaces:
    • \n
    \n
    npm config set cache C:\\tmp\\nodejs\\npm-cache --global\n
  • \n
\n

Next step

⚔ Create your first renderable component.

\n","description":"Create full-stack javascript applications within seconds"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Getting Started - Nullstack","description":"Create full-stack javascript applications within seconds"}} \ No newline at end of file diff --git a/docs/hero.svg b/docs/hero.svg deleted file mode 100644 index dc7dfffe..00000000 --- a/docs/hero.svg +++ /dev/null @@ -1 +0,0 @@ -hero \ No newline at end of file diff --git a/docs/how-to-deploy-a-nullstack-application.html b/docs/how-to-deploy-a-nullstack-application.html deleted file mode 100644 index 729e8145..00000000 --- a/docs/how-to-deploy-a-nullstack-application.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - How to Deploy - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

How to Deploy

With Nullstack it's easy to have your application up and running in production mode.

-
-

🐱‍💻 stonks

-
-

Nullstack compiles your code and all your dependencies using Webpack.

-

The output of the compilation is moved to the .production folder and is the only folder besides public that needs to be moved into the host machine.

-

If you have project.cdn set you must move the public folder to the actual cdn.

-
-

💡 It is important that the .production folder is present for environment detection

-
-

The host machine must have at least node v8.10.0 installed.

-

You don't have to "npm install" in the host machine.

-
-

✨ You can configure the environment using settings and secrets

-
-

To start the server just run:

-
node .production/server.js
-
-
-

✨ It is recommend the usage of a process manager like PM2

-
-

How to Deploy a static generated site with Nullstack

After you generate a static site, all you have to do is move the output folder to any host machine capable of serving HTML.

-

Next step

-

🎉 Congratulations. You are done with the advanced concepts!

-
-

⚔ Learn how to use MongoDB with Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/how-to-deploy-a-nullstack-application/index.html b/docs/how-to-deploy-a-nullstack-application/index.html deleted file mode 100644 index 729e8145..00000000 --- a/docs/how-to-deploy-a-nullstack-application/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - How to Deploy - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

How to Deploy

With Nullstack it's easy to have your application up and running in production mode.

-
-

🐱‍💻 stonks

-
-

Nullstack compiles your code and all your dependencies using Webpack.

-

The output of the compilation is moved to the .production folder and is the only folder besides public that needs to be moved into the host machine.

-

If you have project.cdn set you must move the public folder to the actual cdn.

-
-

💡 It is important that the .production folder is present for environment detection

-
-

The host machine must have at least node v8.10.0 installed.

-

You don't have to "npm install" in the host machine.

-
-

✨ You can configure the environment using settings and secrets

-
-

To start the server just run:

-
node .production/server.js
-
-
-

✨ It is recommend the usage of a process manager like PM2

-
-

How to Deploy a static generated site with Nullstack

After you generate a static site, all you have to do is move the output folder to any host machine capable of serving HTML.

-

Next step

-

🎉 Congratulations. You are done with the advanced concepts!

-
-

⚔ Learn how to use MongoDB with Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/how-to-deploy-a-nullstack-application/index.json b/docs/how-to-deploy-a-nullstack-application/index.json deleted file mode 100644 index 83d72130..00000000 --- a/docs/how-to-deploy-a-nullstack-application/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"How to Deploy","html":"

With Nullstack it's easy to have your application up and running in production mode.

\n
\n

🐱‍💻 stonks

\n
\n

Nullstack compiles your code and all your dependencies using Webpack.

\n

The output of the compilation is moved to the .production folder and is the only folder besides public that needs to be moved into the host machine.

\n

If you have project.cdn set you must move the public folder to the actual cdn.

\n
\n

💡 It is important that the .production folder is present for environment detection

\n
\n

The host machine must have at least node v8.10.0 installed.

\n

You don't have to "npm install" in the host machine.

\n
\n

✨ You can configure the environment using settings and secrets

\n
\n

To start the server just run:

\n
node .production/server.js\n
\n
\n

✨ It is recommend the usage of a process manager like PM2

\n
\n

How to Deploy a static generated site with Nullstack

After you generate a static site, all you have to do is move the output folder to any host machine capable of serving HTML.

\n

Next step

\n

🎉 Congratulations. You are done with the advanced concepts!

\n
\n

⚔ Learn how to use MongoDB with Nullstack.

\n","description":"With Nullstack it's easy to have your application up and running in production mode"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"How to Deploy - Nullstack","description":"With Nullstack it's easy to have your application up and running in production mode"}} \ No newline at end of file diff --git a/docs/how-to-use-facebook-pixel-with-nullstack.html b/docs/how-to-use-facebook-pixel-with-nullstack.html deleted file mode 100644 index 37a08447..00000000 --- a/docs/how-to-use-facebook-pixel-with-nullstack.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - Facebook's Pixel - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Facebook's Pixel

According to developers.facebook.com:

-

"The Facebook pixel is a snippet of JavaScript code that allows you to track visitor activity on your website."

-

You can take advantage of the context and custom events to create a component that dynamically sends Pixel events.

-

Facebook's Pixel can only be called after hydrate to ensure it is running in the client.

-
import Nullstack from 'nullstack';
-
-class FacebookPixel extends Nullstack {
-
-  async hydrate({page, id}) {
-    ! function(f, b, e, v, n, t, s) {
-      if (f.fbq) return;
-      n = f.fbq = function() {
-          n.callMethod ?
-              n.callMethod.apply(n, arguments) : n.queue.push(arguments)
-      };
-      if (!f._fbq) f._fbq = n;
-      n.push = n;
-      n.loaded = !0;
-      n.version = '2.0';
-      n.queue = [];
-      t = b.createElement(e);
-      t.async = !0;
-      t.src = v;
-      s = b.getElementsByTagName(e)[0];
-      s.parentNode.insertBefore(t, s)
-    }(window, document, 'script',
-      'https://connect.facebook.net/en_US/fbevents.js');
-    fbq('init', id);
-    fbq('track', 'PageView');
-    window.addEventListener(page.event, () => {
-      fbq('init', id);
-      fbq('track', 'PageView');
-    })
-  }
-}
-
-export default FacebookPixel;
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from './FacebookPixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="REPLACE_WITH_YOUR_FACEBOOK_PIXEL_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Using a Wrapper

Alternatively, you can install nullstack-facebook-pixel as a dependency:

-
npm install nullstack-facebook-pixel
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from 'nullstack-facebook-pixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="REPLACE_WITH_YOUR_FACEBOOK_PIXEL_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Next step

-

🎉 Congratulations. You are done with the documentation!

-
-

⚔ If you want to see this more examples please open an issue on github.

-
- - - \ No newline at end of file diff --git a/docs/how-to-use-facebook-pixel-with-nullstack/index.html b/docs/how-to-use-facebook-pixel-with-nullstack/index.html deleted file mode 100644 index 37a08447..00000000 --- a/docs/how-to-use-facebook-pixel-with-nullstack/index.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - Facebook's Pixel - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Facebook's Pixel

According to developers.facebook.com:

-

"The Facebook pixel is a snippet of JavaScript code that allows you to track visitor activity on your website."

-

You can take advantage of the context and custom events to create a component that dynamically sends Pixel events.

-

Facebook's Pixel can only be called after hydrate to ensure it is running in the client.

-
import Nullstack from 'nullstack';
-
-class FacebookPixel extends Nullstack {
-
-  async hydrate({page, id}) {
-    ! function(f, b, e, v, n, t, s) {
-      if (f.fbq) return;
-      n = f.fbq = function() {
-          n.callMethod ?
-              n.callMethod.apply(n, arguments) : n.queue.push(arguments)
-      };
-      if (!f._fbq) f._fbq = n;
-      n.push = n;
-      n.loaded = !0;
-      n.version = '2.0';
-      n.queue = [];
-      t = b.createElement(e);
-      t.async = !0;
-      t.src = v;
-      s = b.getElementsByTagName(e)[0];
-      s.parentNode.insertBefore(t, s)
-    }(window, document, 'script',
-      'https://connect.facebook.net/en_US/fbevents.js');
-    fbq('init', id);
-    fbq('track', 'PageView');
-    window.addEventListener(page.event, () => {
-      fbq('init', id);
-      fbq('track', 'PageView');
-    })
-  }
-}
-
-export default FacebookPixel;
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from './FacebookPixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="REPLACE_WITH_YOUR_FACEBOOK_PIXEL_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Using a Wrapper

Alternatively, you can install nullstack-facebook-pixel as a dependency:

-
npm install nullstack-facebook-pixel
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from 'nullstack-facebook-pixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="REPLACE_WITH_YOUR_FACEBOOK_PIXEL_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Next step

-

🎉 Congratulations. You are done with the documentation!

-
-

⚔ If you want to see this more examples please open an issue on github.

-
- - - \ No newline at end of file diff --git a/docs/how-to-use-facebook-pixel-with-nullstack/index.json b/docs/how-to-use-facebook-pixel-with-nullstack/index.json deleted file mode 100644 index 5c577dc2..00000000 --- a/docs/how-to-use-facebook-pixel-with-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Facebook's Pixel","html":"

According to developers.facebook.com:

\n

"The Facebook pixel is a snippet of JavaScript code that allows you to track visitor activity on your website."

\n

You can take advantage of the context and custom events to create a component that dynamically sends Pixel events.

\n

Facebook's Pixel can only be called after hydrate to ensure it is running in the client.

\n
import Nullstack from 'nullstack';\n\nclass FacebookPixel extends Nullstack {\n\n  async hydrate({page, id}) {\n    ! function(f, b, e, v, n, t, s) {\n      if (f.fbq) return;\n      n = f.fbq = function() {\n          n.callMethod ?\n              n.callMethod.apply(n, arguments) : n.queue.push(arguments)\n      };\n      if (!f._fbq) f._fbq = n;\n      n.push = n;\n      n.loaded = !0;\n      n.version = '2.0';\n      n.queue = [];\n      t = b.createElement(e);\n      t.async = !0;\n      t.src = v;\n      s = b.getElementsByTagName(e)[0];\n      s.parentNode.insertBefore(t, s)\n    }(window, document, 'script',\n      'https://connect.facebook.net/en_US/fbevents.js');\n    fbq('init', id);\n    fbq('track', 'PageView');\n    window.addEventListener(page.event, () => {\n      fbq('init', id);\n      fbq('track', 'PageView');\n    })\n  }\n}\n\nexport default FacebookPixel;\n
\n
import Nullstack from 'nullstack';\nimport FacebookPixel from './FacebookPixel';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <FacebookPixel id=\"REPLACE_WITH_YOUR_FACEBOOK_PIXEL_ID\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Using a Wrapper

Alternatively, you can install nullstack-facebook-pixel as a dependency:

\n
npm install nullstack-facebook-pixel\n
\n
import Nullstack from 'nullstack';\nimport FacebookPixel from 'nullstack-facebook-pixel';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <FacebookPixel id=\"REPLACE_WITH_YOUR_FACEBOOK_PIXEL_ID\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Next step

\n

🎉 Congratulations. You are done with the documentation!

\n
\n

⚔ If you want to see this more examples please open an issue on github.

\n","description":"Take advantage of the [context](/context) and [custom events](/context-page) to create a component that dynamically sends Pixel events"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Facebook's Pixel - Nullstack","description":"Take advantage of the [context](/context) and [custom events](/context-page) to create a component that dynamically sends Pixel events"}} \ No newline at end of file diff --git a/docs/how-to-use-google-analytics-with-nullstack.html b/docs/how-to-use-google-analytics-with-nullstack.html deleted file mode 100644 index 9d692c4a..00000000 --- a/docs/how-to-use-google-analytics-with-nullstack.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - Google Analytics - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Google Analytics

According to analytics.google.com:

-

"Google Analytics lets you measure your advertising ROI as well as track your Flash, video, and social networking sites and applications."

-

You can take advantage of the context and custom events to create a component that dynamically sends GTAG events.

-

GTAG can only be called after hydrate to ensure it is running in the client.

-
import Nullstack from 'nullstack';
-
-class GoogleAnalytics extends Nullstack {
-
-  hydrate({router, page, id}) {
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){
-      dataLayer.push(arguments);
-    }
-    gtag('js', new Date());
-    gtag('config', id, {
-      page_title: page.title,
-      page_path: router.url
-    });
-    window.addEventListener(page.event, () => {
-      gtag('event', 'page_view', {
-        page_title: page.title,
-        page_path: router.url
-      })
-    })
-  }
-  
-  render({id}) {
-    return (
-      <script 
-        async
-        src={`https://www.googletagmanager.com/gtag/js?id=${id}`}
-      />
-    )
-  }
-
-}
-
-export default GoogleAnalytics;
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from './GoogleAnalytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="REPLACE_WITH_YOUR_GOOGLE_ANALYTICS_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Using a Wrapper

Alternatively, you can install nullstack-google-analytics as a dependency:

-
npm install nullstack-google-analytics
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from 'nullstack-google-analytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="REPLACE_WITH_YOUR_GOOGLE_ANALYTICS_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn how to use Facebook Pixel with Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/how-to-use-google-analytics-with-nullstack/index.html b/docs/how-to-use-google-analytics-with-nullstack/index.html deleted file mode 100644 index 9d692c4a..00000000 --- a/docs/how-to-use-google-analytics-with-nullstack/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - Google Analytics - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Google Analytics

According to analytics.google.com:

-

"Google Analytics lets you measure your advertising ROI as well as track your Flash, video, and social networking sites and applications."

-

You can take advantage of the context and custom events to create a component that dynamically sends GTAG events.

-

GTAG can only be called after hydrate to ensure it is running in the client.

-
import Nullstack from 'nullstack';
-
-class GoogleAnalytics extends Nullstack {
-
-  hydrate({router, page, id}) {
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){
-      dataLayer.push(arguments);
-    }
-    gtag('js', new Date());
-    gtag('config', id, {
-      page_title: page.title,
-      page_path: router.url
-    });
-    window.addEventListener(page.event, () => {
-      gtag('event', 'page_view', {
-        page_title: page.title,
-        page_path: router.url
-      })
-    })
-  }
-  
-  render({id}) {
-    return (
-      <script 
-        async
-        src={`https://www.googletagmanager.com/gtag/js?id=${id}`}
-      />
-    )
-  }
-
-}
-
-export default GoogleAnalytics;
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from './GoogleAnalytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="REPLACE_WITH_YOUR_GOOGLE_ANALYTICS_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Using a Wrapper

Alternatively, you can install nullstack-google-analytics as a dependency:

-
npm install nullstack-google-analytics
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from 'nullstack-google-analytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="REPLACE_WITH_YOUR_GOOGLE_ANALYTICS_ID" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn how to use Facebook Pixel with Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/how-to-use-google-analytics-with-nullstack/index.json b/docs/how-to-use-google-analytics-with-nullstack/index.json deleted file mode 100644 index f48a1004..00000000 --- a/docs/how-to-use-google-analytics-with-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Google Analytics","html":"

According to analytics.google.com:

\n

"Google Analytics lets you measure your advertising ROI as well as track your Flash, video, and social networking sites and applications."

\n

You can take advantage of the context and custom events to create a component that dynamically sends GTAG events.

\n

GTAG can only be called after hydrate to ensure it is running in the client.

\n
import Nullstack from 'nullstack';\n\nclass GoogleAnalytics extends Nullstack {\n\n  hydrate({router, page, id}) {\n    window.dataLayer = window.dataLayer || [];\n    function gtag(){\n      dataLayer.push(arguments);\n    }\n    gtag('js', new Date());\n    gtag('config', id, {\n      page_title: page.title,\n      page_path: router.url\n    });\n    window.addEventListener(page.event, () => {\n      gtag('event', 'page_view', {\n        page_title: page.title,\n        page_path: router.url\n      })\n    })\n  }\n  \n  render({id}) {\n    return (\n      <script \n        async\n        src={`https://www.googletagmanager.com/gtag/js?id=${id}`}\n      />\n    )\n  }\n\n}\n\nexport default GoogleAnalytics;\n
\n
import Nullstack from 'nullstack';\nimport GoogleAnalytics from './GoogleAnalytics';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <GoogleAnalytics id=\"REPLACE_WITH_YOUR_GOOGLE_ANALYTICS_ID\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Using a Wrapper

Alternatively, you can install nullstack-google-analytics as a dependency:

\n
npm install nullstack-google-analytics\n
\n
import Nullstack from 'nullstack';\nimport GoogleAnalytics from 'nullstack-google-analytics';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <GoogleAnalytics id=\"REPLACE_WITH_YOUR_GOOGLE_ANALYTICS_ID\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Next step

⚔ Learn how to use Facebook Pixel with Nullstack.

\n","description":"Take advantage of the context and custom events to create a component that dynamically sends GTAG events"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Google Analytics - Nullstack","description":"Take advantage of the context and custom events to create a component that dynamically sends GTAG events"}} \ No newline at end of file diff --git a/docs/how-to-use-mongodb-with-nullstack.html b/docs/how-to-use-mongodb-with-nullstack.html deleted file mode 100644 index 6d808877..00000000 --- a/docs/how-to-use-mongodb-with-nullstack.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - How to use MongoDB - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

How to use MongoDB

According to mongodb.com:

-

"MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era."

-

You can use any database with Nullstack, but the javascript integration and flexibility of MongoDB looks especially good with Nullstack applications.

-

Install the MongoDB driver from npm:

-
npm install mongodb
-
-

Configure the database credentials using secrets.

-

The last step is to simply assign the database connection to the server context.

-
import Nullstack from 'nullstack';
-import {MongoClient} from 'mongodb';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    const {secrets} = context;
-    secrets.development.databaseHost = 'mongodb://localhost:27017/dbname';
-    secrets.databaseName = 'dbname';
-    await this.startDatabase(context);
-  }
-
-  static async startDatabase(context) {
-    const {secrets} = context;
-    const databaseClient = new MongoClient(secrets.databaseHost);
-    await databaseClient.connect();
-    context.database = await databaseClient.db(secrets.databaseName);
-  }
-
-}
-
-export default Application;
-
-

The example above will make the database key available to all your server functions.

-
import Nullstack from 'nullstack';
-
-class BooksList extends Nullstack {
-
-  books = [];
-
-  static async getBooks({database}) {
-    return await database.collection('books').find().toArray();
-  }
-
-  async initiate() {
-    this.books = await this.getBooks();
-  }
-
-  // ...
-
-}
-
-export default BooksList;
-
-

Next step

⚔ Learn how to use Google Analytics with Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/how-to-use-mongodb-with-nullstack/index.html b/docs/how-to-use-mongodb-with-nullstack/index.html deleted file mode 100644 index 6d808877..00000000 --- a/docs/how-to-use-mongodb-with-nullstack/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - How to use MongoDB - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

How to use MongoDB

According to mongodb.com:

-

"MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era."

-

You can use any database with Nullstack, but the javascript integration and flexibility of MongoDB looks especially good with Nullstack applications.

-

Install the MongoDB driver from npm:

-
npm install mongodb
-
-

Configure the database credentials using secrets.

-

The last step is to simply assign the database connection to the server context.

-
import Nullstack from 'nullstack';
-import {MongoClient} from 'mongodb';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    const {secrets} = context;
-    secrets.development.databaseHost = 'mongodb://localhost:27017/dbname';
-    secrets.databaseName = 'dbname';
-    await this.startDatabase(context);
-  }
-
-  static async startDatabase(context) {
-    const {secrets} = context;
-    const databaseClient = new MongoClient(secrets.databaseHost);
-    await databaseClient.connect();
-    context.database = await databaseClient.db(secrets.databaseName);
-  }
-
-}
-
-export default Application;
-
-

The example above will make the database key available to all your server functions.

-
import Nullstack from 'nullstack';
-
-class BooksList extends Nullstack {
-
-  books = [];
-
-  static async getBooks({database}) {
-    return await database.collection('books').find().toArray();
-  }
-
-  async initiate() {
-    this.books = await this.getBooks();
-  }
-
-  // ...
-
-}
-
-export default BooksList;
-
-

Next step

⚔ Learn how to use Google Analytics with Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/how-to-use-mongodb-with-nullstack/index.json b/docs/how-to-use-mongodb-with-nullstack/index.json deleted file mode 100644 index abd3435d..00000000 --- a/docs/how-to-use-mongodb-with-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"How to use MongoDB","html":"

According to mongodb.com:

\n

"MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era."

\n

You can use any database with Nullstack, but the javascript integration and flexibility of MongoDB looks especially good with Nullstack applications.

\n

Install the MongoDB driver from npm:

\n
npm install mongodb\n
\n

Configure the database credentials using secrets.

\n

The last step is to simply assign the database connection to the server context.

\n
import Nullstack from 'nullstack';\nimport {MongoClient} from 'mongodb';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    const {secrets} = context;\n    secrets.development.databaseHost = 'mongodb://localhost:27017/dbname';\n    secrets.databaseName = 'dbname';\n    await this.startDatabase(context);\n  }\n\n  static async startDatabase(context) {\n    const {secrets} = context;\n    const databaseClient = new MongoClient(secrets.databaseHost);\n    await databaseClient.connect();\n    context.database = await databaseClient.db(secrets.databaseName);\n  }\n\n}\n\nexport default Application;\n
\n

The example above will make the database key available to all your server functions.

\n
import Nullstack from 'nullstack';\n\nclass BooksList extends Nullstack {\n\n  books = [];\n\n  static async getBooks({database}) {\n    return await database.collection('books').find().toArray();\n  }\n\n  async initiate() {\n    this.books = await this.getBooks();\n  }\n\n  // ...\n\n}\n\nexport default BooksList;\n
\n

Next step

⚔ Learn how to use Google Analytics with Nullstack.

\n","description":"You can use any database with Nullstack, but the javascript integration and flexibility of MongoDB looks especially good with Nullstack applications"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"How to use MongoDB - Nullstack","description":"You can use any database with Nullstack, but the javascript integration and flexibility of MongoDB looks especially good with Nullstack applications"}} \ No newline at end of file diff --git a/docs/icon-128x128.png b/docs/icon-128x128.png deleted file mode 100644 index e96fe8b5..00000000 Binary files a/docs/icon-128x128.png and /dev/null differ diff --git a/docs/icon-144x144.png b/docs/icon-144x144.png deleted file mode 100644 index a87f2a70..00000000 Binary files a/docs/icon-144x144.png and /dev/null differ diff --git a/docs/icon-152x152.png b/docs/icon-152x152.png deleted file mode 100644 index 10b23e29..00000000 Binary files a/docs/icon-152x152.png and /dev/null differ diff --git a/docs/icon-180x180.png b/docs/icon-180x180.png deleted file mode 100644 index 252b3a4f..00000000 Binary files a/docs/icon-180x180.png and /dev/null differ diff --git a/docs/icon-192x192.png b/docs/icon-192x192.png deleted file mode 100644 index 450ca4ca..00000000 Binary files a/docs/icon-192x192.png and /dev/null differ diff --git a/docs/icon-384x384.png b/docs/icon-384x384.png deleted file mode 100644 index c50c7037..00000000 Binary files a/docs/icon-384x384.png and /dev/null differ diff --git a/docs/icon-512x512.png b/docs/icon-512x512.png deleted file mode 100644 index db7461c0..00000000 Binary files a/docs/icon-512x512.png and /dev/null differ diff --git a/docs/icon-72x72.png b/docs/icon-72x72.png deleted file mode 100644 index 58aaf4cd..00000000 Binary files a/docs/icon-72x72.png and /dev/null differ diff --git a/docs/icon-96x96.png b/docs/icon-96x96.png deleted file mode 100644 index a6dd92a8..00000000 Binary files a/docs/icon-96x96.png and /dev/null differ diff --git a/docs/image-1200x630.png b/docs/image-1200x630.png deleted file mode 100644 index 03da34b6..00000000 Binary files a/docs/image-1200x630.png and /dev/null differ diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index c718e73d..00000000 --- a/docs/index.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - Full-stack Javascript Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Full-stack Javascript Components

for one-dev armies

Nullstack is a full-stack framework for building progressive web applications.

It connects a stateful UI layer to specialized microservices in the same component using vanilla javascript.

Focus on solving your business logic instead of writing glue code.

Server-Side Rendering

Nullstack generates SEO ready HTML optimized for the first paint of your route in a single request using local functions with zero javascript dependencies in the client bundle.

Single Page Application

After hydration, requests will fetch JSON from an automatically generated API off server functions, update the application state, and rerender the page.

Static Site Generation

You can even use Nullstack to generate lightning-fast static websites that serve HTML and become a single page application using an automatically generated static API .

Complete Features as Components

Nullstack is not another part of your stack, it is your stack

Your application can be exported from back-end to front-end as a component and mounted into another application

import Nullstack from 'nullstack';
-
-class ProductList extends Nullstack {
-
-  products = [];
-
-  static async getProducts({ database }) {
-    const [products] = await database.query(
-      'SELECT * FROM products'
-    );
-    return products;
-  }
-
-  async initiate() {
-    this.products = await this.getProducts();
-  }
-
-  static async deleteProduct({ database, id }) {
-    await database.query(
-      'DELETE FROM products WHERE id=?', 
-      [id]
-    );
-  }
-
-  async remove({ id }) {
-    await this.deleteProduct({ id });
-    await this.initiate();
-  }
-
-  renderProduct({ id, name }) {
-    return (
-      <li>
-        <button onclick={this.remove} id={id}>
-          {name}
-        </button>    
-      </li>
-    )
-  }
-  
-  render() {
-    return (
-      <ul>
-        {this.products.map((product) => (
-          <Product {...product} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default ProductList;
import Nullstack from 'nullstack';
-
-class ProductForm extends Nullstack {
-
-  name = '';
-  price = 0;
-
-  static async getProductById({ database, id }) {
-    const [products] = await database.query(
-      'SELECT * FROM products WHERE id=? LIMIT 1', 
-      [id]
-    );
-    return products[0];
-  }
-
-  async initiate({ params }) {
-    const product = await this.getProductById({
-      id: params.id
-    });
-    this.name = product.name;
-    this.price = product.price;
-  }
-
-  static async updateProduct({ database, name, price, id }) {
-    await database.query(
-      'UPDATE products SET name=?, price=? WHERE id=?',
-      [name, price, id]
-    );
-  }
-
-  async submit({ router, params }) {
-    await this.updateProduct({
-      id: params.id,
-      name: this.name,
-      price: this.price
-    });
-    router.url = '/products';
-  }
-  
-  render() {
-    return (
-      <form onsubmit={this.submit}>
-        <input class="form-control" bind={this.name} />
-        <input type="number" step=".01" bind={this.price} />
-        <button>Submit</button>
-      </form>
-    )
-  }
-
-}
-
-export default ProductForm;

The example above is the complete code of a product list and edit form without hiding a single line.

Both components invoke server functions to access a MySQL database inside JavaScript without you having to think about APIs

Productivity is in the Details

Nullstack features have been extracted from real life projects with convenience and consistency in mind

import Nullstack from 'nullstack';
-
-class Controlled extends Nullstack {
-
-  count = 0;
-
-  increment({delta}) {
-    this.count += delta;
-  }
-  
-  render() {
-    return (
-      <div>
-        <button onclick={this.increment} delta={-1}> 
-          {this.count}
-        </button>
-        <span> {this.count} </span>
-        <button onclick={this.increment} delta={1}> 
-          {this.count}
-        </button>
-      </div>
-    )
-  }
-
-}
-
-export default Controlled;
import Nullstack from 'nullstack';
-
-class Binding extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  
-  object = {number: 1};
-  array = ['a', 'b', 'c'];
-  
-  render({params}) {
-    return (
-      <form>
-        <input bind={this.number} />
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.number} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </form>
-    )
-  }
-
-}
-
-export default Binding;
import Nullstack from 'nullstack';
-
-class Routes extends Nullstack {
-
-  renderPost({params}) {
-    return (
-      <div>
-        <div route="/post/getting-started">
-          npx create-nullstack-app name
-        </div>
-        <div route="*"> {params.slug} </div>
-      </div>
-    )
-  }
-  
-  render() {
-    return (
-      <div> 
-        <Post route="/post/:slug" />
-        <a href="/post/hello-world"> Welcome </a>
-      </div>
-    )
-  }
-
-}
-
-export default Routes;
import Nullstack from 'nullstack';
-
-class Lifecycle extends Nullstack {
-  
-  prepare({environment}) {
-    const {server, client} = environment;
-  }
-
-  async initiate({environment}) {
-    const {server, client} = environment;
-  }
-
-  async hydrate({environment}) {
-    const {client} = environment;
-  }
-
-  async update({environment}) {
-    const {client} = environment;
-  }
-
-  async terminate({environment}) {
-    const {client} = environment;
-  }
-
-}
-
-export default Lifecycle;

Watch our Nullstack video tutorials

Nullstack cares about making its content as direct to the point and easy to understand as possible

Full-stack with Nullstack - Part 1
Full-stack with Nullstack - Part 2
Full-stack with Nullstack - Part 3

Why should you use Nullstack?

Scalable Development

Every project starts small and becomes complex over time. Scale as you go, no matter the size of the team.

No compromises, no enforcements.

Feature-driven Development

Development of both back and front ends of a feature in the same component in an organized way with ease of overview.

True componentization and code reusability.

Already existing ecosystem

Takes advantage of any isomorphic vanilla Javascript package made throughout history.

All of your application speaks the same language.

Quickly adapt to scope changes

The horizontal structure, as opposed to a hierarchical one, makes it a lot easier to move resources around.

Flexibility over bureaucracy.
Get Started ╰(*°▽°*)╯
- - - \ No newline at end of file diff --git a/docs/index.json b/docs/index.json deleted file mode 100644 index ee4cb221..00000000 --- a/docs/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-1":{"locale":"en-US","i18n":{"title":"Full-stack Javascript Components","description":"Nullstack is a full-stack javascript framework for building progressive web applications","hero":{"heading":"Full-stack Javascript Components","tagline":"for one-dev armies","descriptions":["Nullstack is a full-stack framework for building progressive web applications.","It connects a stateful UI layer to specialized microservices in the same component using vanilla javascript.","Focus on solving your business logic instead of writing glue code."]},"cycle":{"ssr":{"title":"Server-Side Rendering","link":"/server-side-rendering","text":"Nullstack generates SEO ready HTML optimized for the first paint of your route in a single request using local functions with zero javascript dependencies in the client bundle."},"spa":{"title":"Single Page Application","link":"/full-stack-lifecycle","text":"After hydration, requests will fetch JSON from an automatically generated API off server functions, update the application state, and rerender the page."},"ssg":{"title":"Static Site Generation","link":"/static-site-generation","text":"You can even use Nullstack to generate lightning-fast static websites that serve HTML and become a single page application using an automatically generated static API ."}},"about":{"heading":"Complete Features as Components","taglines":["Nullstack is not another part of your stack, it is your stack","Your application can be exported from back-end to front-end as a component and mounted into another application"]},"showcase":{"descriptions":["The example above is the complete code of a product list and edit form without hiding a single line.","Both components invoke server functions to access a MySQL database inside JavaScript without you having to think about APIs"]},"productivity":{"heading":"Productivity is in the Details","tagline":"Nullstack features have been extracted from real life projects with convenience and consistency in mind"},"features":[{"title":"Stateful Components","key":"Stateful","link":"/stateful-components"},{"title":"Two-Way Binding","key":"Binding","link":"/two-way-bindings"},{"title":"Built-in Routes","key":"Routes","link":"/routes-and-params"},{"title":"Full-stack Lifecycle","key":"Lifecycle","link":"/full-stack-lifecycle"}],"playlist":{"heading":"Watch our Nullstack video tutorials","tagline":"Nullstack cares about making its content as direct to the point and easy to understand as possible","videos":[{"title":"Full-stack with Nullstack - Part 1","link":"https://www.youtube.com/watch?v=l23z00GEar8&list=PL5ylYELQy1hyFbguVaShp3XujjdVXLpId","thumbnail":"/thumbnail-en-us-1.webp"},{"title":"Full-stack with Nullstack - Part 2","link":"https://www.youtube.com/watch?v=_i5kKXkhBaM&list=PL5ylYELQy1hyFbguVaShp3XujjdVXLpId","thumbnail":"/thumbnail-en-us-2.webp"},{"title":"Full-stack with Nullstack - Part 3","link":"https://www.youtube.com/watch?v=8PExa5-G1As&list=PL5ylYELQy1hyFbguVaShp3XujjdVXLpId","thumbnail":"/thumbnail-en-us-3.webp"}]},"why":{"heading":"Why should you use Nullstack?","reasons":[{"title":"Scalable Development","description":"Every project starts small and becomes complex over time. Scale as you go, no matter the size of the team.","link":"/about","closer":"No compromises, no enforcements."},{"title":"Feature-driven Development","description":"Development of both back and front ends of a feature in the same component in an organized way with ease of overview.","link":"/about#feature-driven","closer":"True componentization and code reusability."},{"title":"Already existing ecosystem","description":"Takes advantage of any isomorphic vanilla Javascript package made throughout history.","link":"/about#everything-as-vanilla-as-possible","closer":"All of your application speaks the same language."},{"title":"Quickly adapt to scope changes","description":"The horizontal structure, as opposed to a hierarchical one, makes it a lot easier to move resources around.","link":"/about#why-dependency-injection-instead-of-modularity","closer":"Flexibility over bureaucracy."}],"getStarted":{"text":"Get Started","link":"/getting-started"}}}},"n-0-0-1-0-1-0-0-0-0-0":{},"n-0-0-1-0-1-0-1-0-0-0":{},"n-0-0-1-0-1-0-2-0-0-0":{},"ProductList":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass ProductList extends Nullstack {\r\n\r\n products = [];\r\n\r\n static async getProducts({ database }) {\r\n const [products] = await database.query(\r\n 'SELECT * FROM products'\r\n );\r\n return products;\r\n }\r\n\r\n async initiate() {\r\n this.products = await this.getProducts();\r\n }\r\n\r\n static async deleteProduct({ database, id }) {\r\n await database.query(\r\n 'DELETE FROM products WHERE id=?', \r\n [id]\r\n );\r\n }\r\n\r\n async remove({ id }) {\r\n await this.deleteProduct({ id });\r\n await this.initiate();\r\n }\r\n\r\n renderProduct({ id, name }) {\r\n return (\r\n <li>\r\n <button onclick={this.remove} id={id}>\r\n {name}\r\n </button> \r\n </li>\r\n )\r\n }\r\n \r\n render() {\r\n return (\r\n <ul>\r\n {this.products.map((product) => (\r\n <Product {...product} />\r\n ))}\r\n </ul>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default ProductList;"},"ProductForm":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass ProductForm extends Nullstack {\r\n\r\n name = '';\r\n price = 0;\r\n\r\n static async getProductById({ database, id }) {\r\n const [products] = await database.query(\r\n 'SELECT * FROM products WHERE id=? LIMIT 1', \r\n [id]\r\n );\r\n return products[0];\r\n }\r\n\r\n async initiate({ params }) {\r\n const product = await this.getProductById({\r\n id: params.id\r\n });\r\n this.name = product.name;\r\n this.price = product.price;\r\n }\r\n\r\n static async updateProduct({ database, name, price, id }) {\r\n await database.query(\r\n 'UPDATE products SET name=?, price=? WHERE id=?',\r\n [name, price, id]\r\n );\r\n }\r\n\r\n async submit({ router, params }) {\r\n await this.updateProduct({\r\n id: params.id,\r\n name: this.name,\r\n price: this.price\r\n });\r\n router.url = '/products';\r\n }\r\n \r\n render() {\r\n return (\r\n <form onsubmit={this.submit}>\r\n <input class=\"form-control\" bind={this.name} />\r\n <input type=\"number\" step=\".01\" bind={this.price} />\r\n <button>Submit</button>\r\n </form>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default ProductForm;"},"Stateful":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Controlled extends Nullstack {\r\n\r\n count = 0;\r\n\r\n increment({delta}) {\r\n this.count += delta;\r\n }\r\n \r\n render() {\r\n return (\r\n <div>\r\n <button onclick={this.increment} delta={-1}> \r\n {this.count}\r\n </button>\r\n <span> {this.count} </span>\r\n <button onclick={this.increment} delta={1}> \r\n {this.count}\r\n </button>\r\n </div>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default Controlled;"},"Binding":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Binding extends Nullstack {\r\n\r\n number = 1;\r\n boolean = true;\r\n \r\n object = {number: 1};\r\n array = ['a', 'b', 'c'];\r\n \r\n render({params}) {\r\n return (\r\n <form>\r\n <input bind={this.number} />\r\n <input bind={this.boolean} type=\"checkbox\" />\r\n <input bind={this.object.number} />\r\n {this.array.map((value, index) => (\r\n <input bind={this.array[index]} />\r\n ))}\r\n <input bind={params.page} />\r\n </form>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default Binding;"},"Routes":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Routes extends Nullstack {\r\n\r\n renderPost({params}) {\r\n return (\r\n <div>\r\n <div route=\"/post/getting-started\">\r\n npx create-nullstack-app name\r\n </div>\r\n <div route=\"*\"> {params.slug} </div>\r\n </div>\r\n )\r\n }\r\n \r\n render() {\r\n return (\r\n <div> \r\n <Post route=\"/post/:slug\" />\r\n <a href=\"/post/hello-world\"> Welcome </a>\r\n </div>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default Routes;"},"Lifecycle":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Lifecycle extends Nullstack {\r\n \r\n prepare({environment}) {\r\n const {server, client} = environment;\r\n }\r\n\r\n async initiate({environment}) {\r\n const {server, client} = environment;\r\n }\r\n\r\n async hydrate({environment}) {\r\n const {client} = environment;\r\n }\r\n\r\n async update({environment}) {\r\n const {client} = environment;\r\n }\r\n\r\n async terminate({environment}) {\r\n const {client} = environment;\r\n }\r\n\r\n}\r\n\r\nexport default Lifecycle;"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"priority":1,"title":"Full-stack Javascript Components - Nullstack","description":"Nullstack is a full-stack javascript framework for building progressive web applications","locale":"en-US"}} \ No newline at end of file diff --git a/docs/instance-self.html b/docs/instance-self.html deleted file mode 100644 index 7bdf1d27..00000000 --- a/docs/instance-self.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - Instance Self - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Instance Self

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: client
  • -
  • readonly in client context
  • -
-

It gives you information about the instance lifecycle and it's unique key.

-

Each instance receives its own self object.

-

The following keys are available in the object:

-
    -
  • key: string
  • -
-

When a lifecycle method is resolved, even if not declared, an equivalent key is set to true in self.

-

If the component was server-side rendered the prerendered key will remain true until it is terminated.

-

The element key points to the DOM selector and is only guaranteed to exist when hydrate is being called since prepare and initiate could run in the server.

-
-

💡 Do not use element to guess the environment, instead use the environment for that.

-
-

Observing self is a nice way to avoid giving placeholder information to the end-user.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.price = await this.getPrice();
-  }
-
-  async hydrate({self}) {
-    self.element.querySelector('input').focus();
-  }
- 
-  render({self}) {
-    if(!self.prerendered && !self.initiated) return false;
-    return (
-      <form> 
-        <input type="number" bind={this.price} />
-        <button disabled={!self.hydrated}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-
-

💡 Components that get optimized into functional components have no access to self.

-
-

Instance Key

    -
  • Type: string
  • -
  • Origin: Component Context
  • -
  • Availability: client
  • -
  • readonly in client context or after defined it's value as attribute
  • -
-

It allows you to persist the instance when it moves in the dom.

-

You can declare one key per instance.

-
-

💡 If you do not declare a key nullstack will generate one based on dom depth.

-
-
-

🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys

-
-

Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings.

-

Preserving state

Keys are useful to preserve state in stateful components when you move them in the dom.

-

This is especially useful for dynamically sized lists that invoke components.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Shared Instances

You can also use keys to share the instance between two elements.

-

Only the first encounter of the key will run its lifecycle.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Instance Key

    -
  • Type: string
  • -
  • Origin: Component Context
  • -
  • Availability: client
  • -
  • readonly in client context or after defined it's value as attribute
  • -
-

It allows you to persist the instance when it moves in the dom.

-

You can declare one key per instance.

-
-

💡 If you do not declare a key nullstack will generate one based on dom depth.

-
-
-

🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys

-
-

Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings.

-

Preserving state

Keys are useful to preserve state in stateful components when you move them in the dom.

-

This is especially useful for dynamically sized lists that invoke components.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Shared Instances

You can also use keys to share the instance between two elements.

-

Only the first encounter of the key will run its lifecycle

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn about the server request and response.

-
- - - \ No newline at end of file diff --git a/docs/instance-self/index.html b/docs/instance-self/index.html deleted file mode 100644 index 7bdf1d27..00000000 --- a/docs/instance-self/index.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - Instance Self - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Instance Self

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: client
  • -
  • readonly in client context
  • -
-

It gives you information about the instance lifecycle and it's unique key.

-

Each instance receives its own self object.

-

The following keys are available in the object:

-
    -
  • key: string
  • -
-

When a lifecycle method is resolved, even if not declared, an equivalent key is set to true in self.

-

If the component was server-side rendered the prerendered key will remain true until it is terminated.

-

The element key points to the DOM selector and is only guaranteed to exist when hydrate is being called since prepare and initiate could run in the server.

-
-

💡 Do not use element to guess the environment, instead use the environment for that.

-
-

Observing self is a nice way to avoid giving placeholder information to the end-user.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.price = await this.getPrice();
-  }
-
-  async hydrate({self}) {
-    self.element.querySelector('input').focus();
-  }
- 
-  render({self}) {
-    if(!self.prerendered && !self.initiated) return false;
-    return (
-      <form> 
-        <input type="number" bind={this.price} />
-        <button disabled={!self.hydrated}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-
-

💡 Components that get optimized into functional components have no access to self.

-
-

Instance Key

    -
  • Type: string
  • -
  • Origin: Component Context
  • -
  • Availability: client
  • -
  • readonly in client context or after defined it's value as attribute
  • -
-

It allows you to persist the instance when it moves in the dom.

-

You can declare one key per instance.

-
-

💡 If you do not declare a key nullstack will generate one based on dom depth.

-
-
-

🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys

-
-

Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings.

-

Preserving state

Keys are useful to preserve state in stateful components when you move them in the dom.

-

This is especially useful for dynamically sized lists that invoke components.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Shared Instances

You can also use keys to share the instance between two elements.

-

Only the first encounter of the key will run its lifecycle.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Instance Key

    -
  • Type: string
  • -
  • Origin: Component Context
  • -
  • Availability: client
  • -
  • readonly in client context or after defined it's value as attribute
  • -
-

It allows you to persist the instance when it moves in the dom.

-

You can declare one key per instance.

-
-

💡 If you do not declare a key nullstack will generate one based on dom depth.

-
-
-

🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys

-
-

Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings.

-

Preserving state

Keys are useful to preserve state in stateful components when you move them in the dom.

-

This is especially useful for dynamically sized lists that invoke components.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Shared Instances

You can also use keys to share the instance between two elements.

-

Only the first encounter of the key will run its lifecycle

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn about the server request and response.

-
- - - \ No newline at end of file diff --git a/docs/instance-self/index.json b/docs/instance-self/index.json deleted file mode 100644 index 9062d5c9..00000000 --- a/docs/instance-self/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Instance Self","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: client
  • \n
  • readonly in client context
  • \n
\n

It gives you information about the instance lifecycle and it's unique key.

\n

Each instance receives its own self object.

\n

The following keys are available in the object:

\n
    \n
  • key: string
  • \n
\n

When a lifecycle method is resolved, even if not declared, an equivalent key is set to true in self.

\n

If the component was server-side rendered the prerendered key will remain true until it is terminated.

\n

The element key points to the DOM selector and is only guaranteed to exist when hydrate is being called since prepare and initiate could run in the server.

\n
\n

💡 Do not use element to guess the environment, instead use the environment for that.

\n
\n

Observing self is a nice way to avoid giving placeholder information to the end-user.

\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.price = await this.getPrice();\n  }\n\n  async hydrate({self}) {\n    self.element.querySelector('input').focus();\n  }\n \n  render({self}) {\n    if(!self.prerendered && !self.initiated) return false;\n    return (\n      <form> \n        <input type=\"number\" bind={this.price} />\n        <button disabled={!self.hydrated}> \n          Save\n        </button>\n      </form>\n    )\n  }\n\n}\n\nexport default Page;\n
\n
\n

💡 Components that get optimized into functional components have no access to self.

\n
\n

Instance Key

    \n
  • Type: string
  • \n
  • Origin: Component Context
  • \n
  • Availability: client
  • \n
  • readonly in client context or after defined it's value as attribute
  • \n
\n

It allows you to persist the instance when it moves in the dom.

\n

You can declare one key per instance.

\n
\n

💡 If you do not declare a key nullstack will generate one based on dom depth.

\n
\n
\n

🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys

\n
\n

Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings.

\n

Preserving state

Keys are useful to preserve state in stateful components when you move them in the dom.

\n

This is especially useful for dynamically sized lists that invoke components.

\n
import Nullstack from 'nullstack';\nimport Item from './Item';\n\nclass List extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.items = await this.getItems();\n  }\n \n  render({self}) {\n    const componentKey = self.key;\n    return (\n      <ul> \n        {this.items.map((item) => (\n          <Item key={`${componentKey}-${item.id}`} {...item} />\n        ))}\n      </ul>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Shared Instances

You can also use keys to share the instance between two elements.

\n

Only the first encounter of the key will run its lifecycle.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  render({amount}) {\n    return (\n      <div>\n        <button onclick={{count: this.count+1}}>\n          {this.count} x {amount} = {this.count * amount}\n        </button>  \n      </div>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  render() {\n    return (\n      <main>\n        <Counter key=\"a\" amount={1} />\n        <Counter key=\"b\" amount={2} />\n        <Counter key=\"b\" amount={3} />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Instance Key

    \n
  • Type: string
  • \n
  • Origin: Component Context
  • \n
  • Availability: client
  • \n
  • readonly in client context or after defined it's value as attribute
  • \n
\n

It allows you to persist the instance when it moves in the dom.

\n

You can declare one key per instance.

\n
\n

💡 If you do not declare a key nullstack will generate one based on dom depth.

\n
\n
\n

🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys

\n
\n

Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings.

\n

Preserving state

Keys are useful to preserve state in stateful components when you move them in the dom.

\n

This is especially useful for dynamically sized lists that invoke components.

\n
import Nullstack from 'nullstack';\nimport Item from './Item';\n\nclass List extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.items = await this.getItems();\n  }\n \n  render({self}) {\n    const componentKey = self.key;\n    return (\n      <ul> \n        {this.items.map((item) => (\n          <Item key={`${componentKey}-${item.id}`} {...item} />\n        ))}\n      </ul>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Shared Instances

You can also use keys to share the instance between two elements.

\n

Only the first encounter of the key will run its lifecycle

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  render({amount}) {\n    return (\n      <div>\n        <button onclick={{count: this.count+1}}>\n          {this.count} x {amount} = {this.count * amount}\n        </button>  \n      </div>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  render() {\n    return (\n      <main>\n        <Counter key=\"a\" amount={1} />\n        <Counter key=\"b\" amount={2} />\n        <Counter key=\"b\" amount={3} />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Next step

⚔ Learn about the server request and response.

\n","description":"The self object is a proxy in the Nullstack Context available in client and gives you information about the instance lifecycle"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Instance Self - Nullstack","description":"The self object is a proxy in the Nullstack Context available in client and gives you information about the instance lifecycle"}} \ No newline at end of file diff --git a/docs/manifest-9cdb5778f42a90a83e1427c9316c97d3.json b/docs/manifest-9cdb5778f42a90a83e1427c9316c97d3.json deleted file mode 100644 index 3b29c313..00000000 --- a/docs/manifest-9cdb5778f42a90a83e1427c9316c97d3.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"Nullstack","short_name":"Nullstack","theme_color":"#d22365","background_color":"#2d3748","display":"standalone","orientation":"portrait","scope":"/","start_url":"/","icons":[{"src":"/icon-72x72.png","sizes":"72x72","type":"image/png","purpose":"maskable any"},{"src":"/icon-96x96.png","sizes":"96x96","type":"image/png","purpose":"maskable any"},{"src":"/icon-128x128.png","sizes":"128x128","type":"image/png","purpose":"maskable any"},{"src":"/icon-144x144.png","sizes":"144x144","type":"image/png","purpose":"maskable any"},{"src":"/icon-152x152.png","sizes":"152x152","type":"image/png","purpose":"maskable any"},{"src":"/icon-180x180.png","sizes":"180x180","type":"image/png","purpose":"maskable any"},{"src":"/icon-192x192.png","sizes":"192x192","type":"image/png","purpose":"maskable any"},{"src":"/icon-384x384.png","sizes":"384x384","type":"image/png","purpose":"maskable any"},{"src":"/icon-512x512.png","sizes":"512x512","type":"image/png","purpose":"maskable any"}],"splash_pages":null} \ No newline at end of file diff --git a/docs/njs-file-extension.html b/docs/njs-file-extension.html deleted file mode 100644 index 8bbeecd6..00000000 --- a/docs/njs-file-extension.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - NJS File Extension - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

NJS File Extension

Nullstack Javascript files let Webpack know which loaders to use at transpile time.

-

NJS files must import Nullstack or one of its subclasses.

-

If only a subclass is imported, a Nullstack import will be injected at transpile time.

-

At transpile time JSX tags will be replaced with Nullstack.element.

-

This extension also allows Nullstack to make free transpile time optimizations like source injection.

-
-

🔥 Each file must have only one class declaration.

-
-
    -
  • On the server bundle static async functions are mapped into a registry for security.
  • -
  • On the client bundle static async functions are removed and replaced with a invoke method.
  • -
  • On the client bundle static async functions with the name starting with "start" (and optionally followed by an uppercase letter) are completely removed.
  • -
  • On both server and client bundles, a hash with the md5 of the original source code is added to the class.
  • -
-
-

🐱‍💻 Bellow an example of a original .njs file.

-
-
import List from './List';
-import {readFileSync} from 'fs';
-
-class Tasks extends List {
-
-  static async getTasks({limit}) {
-    const json = readFileSync('tasks.json', 'utf-8');
-    return JSON.parse(json).tasks.slice(0, limit);
-  }
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input bind={task.description} />
-      </li>
-    )
-  }
-
-  render() {
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-
-

🐱‍💻 Bellow an example of the same transpiled .njs file.

-
-
import Nullstack from 'nullstack';
-import List from './List';
-
-class Tasks extends List {
-
-  static hash = 'd493ac09d0d57574a30f136d31da455f';
-
-  static getTasks = Nullstack.invoke('getTasks', 'd493ac09d0d57574a30f136d31da455f');
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input source={task} bind="description" />
-      </li>
-    )
-  }
-
-  render() {
-    const Task = this.renderTask;
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-

Next step

⚔ Learn about server-side rendering.

-
- - - \ No newline at end of file diff --git a/docs/njs-file-extension/index.html b/docs/njs-file-extension/index.html deleted file mode 100644 index 8bbeecd6..00000000 --- a/docs/njs-file-extension/index.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - NJS File Extension - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

NJS File Extension

Nullstack Javascript files let Webpack know which loaders to use at transpile time.

-

NJS files must import Nullstack or one of its subclasses.

-

If only a subclass is imported, a Nullstack import will be injected at transpile time.

-

At transpile time JSX tags will be replaced with Nullstack.element.

-

This extension also allows Nullstack to make free transpile time optimizations like source injection.

-
-

🔥 Each file must have only one class declaration.

-
-
    -
  • On the server bundle static async functions are mapped into a registry for security.
  • -
  • On the client bundle static async functions are removed and replaced with a invoke method.
  • -
  • On the client bundle static async functions with the name starting with "start" (and optionally followed by an uppercase letter) are completely removed.
  • -
  • On both server and client bundles, a hash with the md5 of the original source code is added to the class.
  • -
-
-

🐱‍💻 Bellow an example of a original .njs file.

-
-
import List from './List';
-import {readFileSync} from 'fs';
-
-class Tasks extends List {
-
-  static async getTasks({limit}) {
-    const json = readFileSync('tasks.json', 'utf-8');
-    return JSON.parse(json).tasks.slice(0, limit);
-  }
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input bind={task.description} />
-      </li>
-    )
-  }
-
-  render() {
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-
-

🐱‍💻 Bellow an example of the same transpiled .njs file.

-
-
import Nullstack from 'nullstack';
-import List from './List';
-
-class Tasks extends List {
-
-  static hash = 'd493ac09d0d57574a30f136d31da455f';
-
-  static getTasks = Nullstack.invoke('getTasks', 'd493ac09d0d57574a30f136d31da455f');
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input source={task} bind="description" />
-      </li>
-    )
-  }
-
-  render() {
-    const Task = this.renderTask;
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-

Next step

⚔ Learn about server-side rendering.

-
- - - \ No newline at end of file diff --git a/docs/njs-file-extension/index.json b/docs/njs-file-extension/index.json deleted file mode 100644 index 948b5151..00000000 --- a/docs/njs-file-extension/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"NJS File Extension","html":"

Nullstack Javascript files let Webpack know which loaders to use at transpile time.

\n

NJS files must import Nullstack or one of its subclasses.

\n

If only a subclass is imported, a Nullstack import will be injected at transpile time.

\n

At transpile time JSX tags will be replaced with Nullstack.element.

\n

This extension also allows Nullstack to make free transpile time optimizations like source injection.

\n
\n

🔥 Each file must have only one class declaration.

\n
\n
    \n
  • On the server bundle static async functions are mapped into a registry for security.
  • \n
  • On the client bundle static async functions are removed and replaced with a invoke method.
  • \n
  • On the client bundle static async functions with the name starting with "start" (and optionally followed by an uppercase letter) are completely removed.
  • \n
  • On both server and client bundles, a hash with the md5 of the original source code is added to the class.
  • \n
\n
\n

🐱‍💻 Bellow an example of a original .njs file.

\n
\n
import List from './List';\nimport {readFileSync} from 'fs';\n\nclass Tasks extends List {\n\n  static async getTasks({limit}) {\n    const json = readFileSync('tasks.json', 'utf-8');\n    return JSON.parse(json).tasks.slice(0, limit);\n  }\n\n  prepare(context) {\n    context.tasks = [];\n  }\n\n  async initiate(context) {\n    context.tasks = await this.getTasks({limit: 10});\n  }\n\n  renderTask({task}) {\n    return (\n      <li> \n        <input bind={task.description} />\n      </li>\n    )\n  }\n\n  render() {\n    return (\n      <main>\n        <ul>\n          {tasks.map((task) => <Task task={task} />)}\n        </ul>\n      </main>\n    )\n  }\n\n}\n\nexport default Tasks;\n
\n
\n

🐱‍💻 Bellow an example of the same transpiled .njs file.

\n
\n
import Nullstack from 'nullstack';\nimport List from './List';\n\nclass Tasks extends List {\n\n  static hash = 'd493ac09d0d57574a30f136d31da455f';\n\n  static getTasks = Nullstack.invoke('getTasks', 'd493ac09d0d57574a30f136d31da455f');\n\n  prepare(context) {\n    context.tasks = [];\n  }\n\n  async initiate(context) {\n    context.tasks = await this.getTasks({limit: 10});\n  }\n\n  renderTask({task}) {\n    return (\n      <li> \n        <input source={task} bind=\"description\" />\n      </li>\n    )\n  }\n\n  render() {\n    const Task = this.renderTask;\n    return (\n      <main>\n        <ul>\n          {tasks.map((task) => <Task task={task} />)}\n        </ul>\n      </main>\n    )\n  }\n\n}\n\nexport default Tasks;\n
\n

Next step

⚔ Learn about server-side rendering.

\n","description":"Nullstack Javascript files let Webpack know which loaders to use at transpile time"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"NJS File Extension - Nullstack","description":"Nullstack Javascript files let Webpack know which loaders to use at transpile time"}} \ No newline at end of file diff --git a/docs/nullachan.png b/docs/nullachan.png deleted file mode 100644 index 0f5ccd45..00000000 Binary files a/docs/nullachan.png and /dev/null differ diff --git a/docs/offline-9cdb5778f42a90a83e1427c9316c97d3.html b/docs/offline-9cdb5778f42a90a83e1427c9316c97d3.html deleted file mode 100644 index 4ddca07a..00000000 --- a/docs/offline-9cdb5778f42a90a83e1427c9316c97d3.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Page Not Found - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Page Not Found

- - - \ No newline at end of file diff --git a/docs/offline-9cdb5778f42a90a83e1427c9316c97d3/index.html b/docs/offline-9cdb5778f42a90a83e1427c9316c97d3/index.html deleted file mode 100644 index 4ddca07a..00000000 --- a/docs/offline-9cdb5778f42a90a83e1427c9316c97d3/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Page Not Found - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Page Not Found

- - - \ No newline at end of file diff --git a/docs/offline-9cdb5778f42a90a83e1427c9316c97d3/index.json b/docs/offline-9cdb5778f42a90a83e1427c9316c97d3/index.json deleted file mode 100644 index d143095b..00000000 --- a/docs/offline-9cdb5778f42a90a83e1427c9316c97d3/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Page Not Found","html":"

Perhaps you want to learn about how to make a 404 page with Nullstack?

\n

If you are looking for something else, you should read the documentation.

\n","description":"Sorry, this is not the page you are looking for.","status":404},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Page Not Found - Nullstack","description":"Sorry, this is not the page you are looking for."}} \ No newline at end of file diff --git a/docs/pt-br.html b/docs/pt-br.html deleted file mode 100644 index af0b34af..00000000 --- a/docs/pt-br.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - Componentes Javascript Full-stack - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes Javascript Full-stack

para exércitos de um dev só

Nullstack é um framework full-stack para construir aplicações web progressivas.

Ele conecta uma camada de UI com estado a microserviços especializados no mesmo componente usando vanilla javascript.

Concentre-se em resolver sua lógica de negócios em vez de escrever código para interoperabilidade.

Renderização no Servidor

Nullstack gera HTML otimizado e com SEO pronto para o primeiro rascunho de sua rota em uma única requisição usando funções locais e com zero dependências javascript no cliente.

Single Page Application

Após hidratação, requisições irão buscar JSON de uma API gerada automaticamente por funções do servidor, atualizar o estado da aplicação e renderizar a página novamente.

Geração de Site Estático

Você pode até usar o Nullstack para gerar sites estáticos ultra-rápidos que servem HTML e se tornam uma Single Page Application usando uma API estática gerada automaticamente.

Recursos Completos como Componentes

Nullstack não é apenas outra parte de sua stack, mas sim a sua stack

Sua aplicação pode ser exportado do back-end para o front-end como um componente e montado em outra aplicação

import Nullstack from 'nullstack';
-
-class ProductList extends Nullstack {
-
-  products = [];
-
-  static async getProducts({ database }) {
-    const [products] = await database.query(
-      'SELECT * FROM products'
-    );
-    return products;
-  }
-
-  async initiate() {
-    this.products = await this.getProducts();
-  }
-
-  static async deleteProduct({ database, id }) {
-    await database.query(
-      'DELETE FROM products WHERE id=?', 
-      [id]
-    );
-  }
-
-  async remove({ id }) {
-    await this.deleteProduct({ id });
-    await this.initiate();
-  }
-
-  renderProduct({ id, name }) {
-    return (
-      <li>
-        <button onclick={this.remove} id={id}>
-          {name}
-        </button>    
-      </li>
-    )
-  }
-  
-  render() {
-    return (
-      <ul>
-        {this.products.map((product) => (
-          <Product {...product} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default ProductList;
import Nullstack from 'nullstack';
-
-class ProductForm extends Nullstack {
-
-  name = '';
-  price = 0;
-
-  static async getProductById({ database, id }) {
-    const [products] = await database.query(
-      'SELECT * FROM products WHERE id=? LIMIT 1', 
-      [id]
-    );
-    return products[0];
-  }
-
-  async initiate({ params }) {
-    const product = await this.getProductById({
-      id: params.id
-    });
-    this.name = product.name;
-    this.price = product.price;
-  }
-
-  static async updateProduct({ database, name, price, id }) {
-    await database.query(
-      'UPDATE products SET name=?, price=? WHERE id=?',
-      [name, price, id]
-    );
-  }
-
-  async submit({ router, params }) {
-    await this.updateProduct({
-      id: params.id,
-      name: this.name,
-      price: this.price
-    });
-    router.url = '/products';
-  }
-  
-  render() {
-    return (
-      <form onsubmit={this.submit}>
-        <input class="form-control" bind={this.name} />
-        <input type="number" step=".01" bind={this.price} />
-        <button>Submit</button>
-      </form>
-    )
-  }
-
-}
-
-export default ProductForm;

O exemplo acima é o código completo de uma listagem de produtos e um formulário de edição sem esconder nenhuma linha.

Ambos os componentes invocam funções de servidor para ter acesso ao banco de dados MySQL no meio do JavaScript sem você ter que pensar em APIs.

A Produtividade está nos Detalhes

Os recursos do Nullstack foram extraídos de projetos da vida real com conveniência e consistência em mente

import Nullstack from 'nullstack';
-
-class Controlled extends Nullstack {
-
-  count = 0;
-
-  increment({delta}) {
-    this.count += delta;
-  }
-  
-  render() {
-    return (
-      <div>
-        <button onclick={this.increment} delta={-1}> 
-          {this.count}
-        </button>
-        <span> {this.count} </span>
-        <button onclick={this.increment} delta={1}> 
-          {this.count}
-        </button>
-      </div>
-    )
-  }
-
-}
-
-export default Controlled;
import Nullstack from 'nullstack';
-
-class Binding extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  
-  object = {number: 1};
-  array = ['a', 'b', 'c'];
-  
-  render({params}) {
-    return (
-      <form>
-        <input bind={this.number} />
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.number} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </form>
-    )
-  }
-
-}
-
-export default Binding;
import Nullstack from 'nullstack';
-
-class Routes extends Nullstack {
-
-  renderPost({params}) {
-    return (
-      <div>
-        <div route="/post/getting-started">
-          npx create-nullstack-app name
-        </div>
-        <div route="*"> {params.slug} </div>
-      </div>
-    )
-  }
-  
-  render() {
-    return (
-      <div> 
-        <Post route="/post/:slug" />
-        <a href="/post/hello-world"> Welcome </a>
-      </div>
-    )
-  }
-
-}
-
-export default Routes;
import Nullstack from 'nullstack';
-
-class Lifecycle extends Nullstack {
-  
-  prepare({environment}) {
-    const {server, client} = environment;
-  }
-
-  async initiate({environment}) {
-    const {server, client} = environment;
-  }
-
-  async hydrate({environment}) {
-    const {client} = environment;
-  }
-
-  async update({environment}) {
-    const {client} = environment;
-  }
-
-  async terminate({environment}) {
-    const {client} = environment;
-  }
-
-}
-
-export default Lifecycle;

Assista aos nossos vídeos tutoriais do Nullstack

Nullstack se preocupa em tornar seu conteúdo o mais direto ao ponto e fácil de entender quanto possível

Full-stack com Nullstack - Parte 1
Full-stack com Nullstack - Parte 2
Full-stack com Nullstack - Parte 3

Por que você deve usar o Nullstack?

Desenvolvimento Escalável

Cada projeto começa pequeno e se torna complexo com o tempo. Escale conforme avança, não importa o tamanho da equipe.

Sem compromissos, sem imposições.

Desenvolvimento Orientado a Recursos

Desenvolvimento de back e front end de um recurso no mesmo componente de forma organizada com facilidade de visão geral.

Verdadeira componentização e reutilização de código.

Ecossistema já existente

Tira proveito de todo e qualquer pacote isomórfico em Vanilla Javascript já feito em toda história.

Todo o sua aplicação fala a mesma língua.

Adapte-se rapidamente às mudanças de escopo

A estrutura horizontal, ao contrário de uma hierárquica, torna muito mais fácil mover os recursos.

Flexibilidade acima de burocracia.
Começar! ╰(*°▽°*)╯
- - - \ No newline at end of file diff --git a/docs/pt-br/ciclo-de-vida-full-stack.html b/docs/pt-br/ciclo-de-vida-full-stack.html deleted file mode 100644 index 0654c09e..00000000 --- a/docs/pt-br/ciclo-de-vida-full-stack.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - Ciclo de Vida Full-Stack - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Ciclo de Vida Full-Stack

Métodos de ciclo de vida são funções nomeadas de forma especial que você pode declarar na classe.

-

Cada método de ciclo de vida roda em uma fila de ordem específica, garantindo que todos os componentes do ciclo atual sejam preparados antes do primeiro ser iniciado.

-

Prepare

Esse método é bloqueante e roda antes da primeira renderização do componente.

-

Você pode usar essa função para definir o estado que o usuário verá antes do carregamento.

-

Se o usuário estiver entrando através dessa rota, prepare irá rodar no servidor antes do Nullstack renderizar sua aplicação no lado do servidor.

-

Se o usuário estiver navegando por outra rota, esse método rodará no cliente.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  prepare() {
-    this.date = new Date();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Initiate

Esse método pode ser assíncrono, e roda assim que o componente for preparado e renderizado pela primeira vez.

-

Você pode usá-lo para invocar outra função do servidor e carregar os dados para apresentar a página.

-

Se o usuário estiver entrando através dessa rota, initiate rodará no servidor.

-

Nullstack irá esperar até que a promise seja resolvida e então finalmente irá gerar o HTML que será servido.

-

Se o usuário estiver navegando por outra rota, esse método rodará no cliente.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.task = await getTaskByDay({
-      day: this.date
-    });
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Aprenda mais sobre funções do servidor.

-
-

Hydrate

Esse método é assíncrono e rodará apenas no cliente.

-

Ele sempre rodará independente do ambiente que iniciou o componente.

-

Esse é um bom lugar para acionar dependências que manipulam o DOM ou que podem rodar apenas no lado do cliente.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async hydrate() {
-    this.timer = setInterval(() => {
-      console.log(this.date);
-    }, 1000);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Update

Esse método é assíncrono e rodará apenas no cliente.

-

Ele roda em todos os componentes sempre que o estado da aplicação mudar.

-
-

🔥 Tome cuidado para não causar loops infinitos quando mutacionar o estado dentro de update.

-
-

Ele irá rodar logo antes da renderização, mas não irá bloquear a fila.

-

A função update não rodará até que a aplicação seja renderizada após initiate.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async update() {
-    const today = new Date();
-    if(today.getDay() != this.date.getDay()) {
-      this.date = today;
-      await this.initiate();
-    }
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Métodos de ciclo de vida não têm efeitos colaterais, você pode chamá-los manualmentes sem causar problemas.

-
-

Terminate

Esse método é assíncrono e rodará apenas no cliente.

-

Ele irá rodar após o componente deixar o DOM.

-

Esse é o lugar para limpar qualquer coisa que você definiu no método hydrate.

-

Essa instância será levada pelo garbage collector após a resolução da Promise.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async terminate() {
-    clearInterval(this.timer);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Próximos passos

⚔ Aprenda sobre funções do servidor.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/ciclo-de-vida-full-stack/index.html b/docs/pt-br/ciclo-de-vida-full-stack/index.html deleted file mode 100644 index 0654c09e..00000000 --- a/docs/pt-br/ciclo-de-vida-full-stack/index.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - Ciclo de Vida Full-Stack - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Ciclo de Vida Full-Stack

Métodos de ciclo de vida são funções nomeadas de forma especial que você pode declarar na classe.

-

Cada método de ciclo de vida roda em uma fila de ordem específica, garantindo que todos os componentes do ciclo atual sejam preparados antes do primeiro ser iniciado.

-

Prepare

Esse método é bloqueante e roda antes da primeira renderização do componente.

-

Você pode usar essa função para definir o estado que o usuário verá antes do carregamento.

-

Se o usuário estiver entrando através dessa rota, prepare irá rodar no servidor antes do Nullstack renderizar sua aplicação no lado do servidor.

-

Se o usuário estiver navegando por outra rota, esse método rodará no cliente.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  prepare() {
-    this.date = new Date();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Initiate

Esse método pode ser assíncrono, e roda assim que o componente for preparado e renderizado pela primeira vez.

-

Você pode usá-lo para invocar outra função do servidor e carregar os dados para apresentar a página.

-

Se o usuário estiver entrando através dessa rota, initiate rodará no servidor.

-

Nullstack irá esperar até que a promise seja resolvida e então finalmente irá gerar o HTML que será servido.

-

Se o usuário estiver navegando por outra rota, esse método rodará no cliente.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.task = await getTaskByDay({
-      day: this.date
-    });
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Aprenda mais sobre funções do servidor.

-
-

Hydrate

Esse método é assíncrono e rodará apenas no cliente.

-

Ele sempre rodará independente do ambiente que iniciou o componente.

-

Esse é um bom lugar para acionar dependências que manipulam o DOM ou que podem rodar apenas no lado do cliente.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async hydrate() {
-    this.timer = setInterval(() => {
-      console.log(this.date);
-    }, 1000);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Update

Esse método é assíncrono e rodará apenas no cliente.

-

Ele roda em todos os componentes sempre que o estado da aplicação mudar.

-
-

🔥 Tome cuidado para não causar loops infinitos quando mutacionar o estado dentro de update.

-
-

Ele irá rodar logo antes da renderização, mas não irá bloquear a fila.

-

A função update não rodará até que a aplicação seja renderizada após initiate.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async update() {
-    const today = new Date();
-    if(today.getDay() != this.date.getDay()) {
-      this.date = today;
-      await this.initiate();
-    }
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Métodos de ciclo de vida não têm efeitos colaterais, você pode chamá-los manualmentes sem causar problemas.

-
-

Terminate

Esse método é assíncrono e rodará apenas no cliente.

-

Ele irá rodar após o componente deixar o DOM.

-

Esse é o lugar para limpar qualquer coisa que você definiu no método hydrate.

-

Essa instância será levada pelo garbage collector após a resolução da Promise.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async terminate() {
-    clearInterval(this.timer);
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Próximos passos

⚔ Aprenda sobre funções do servidor.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/ciclo-de-vida-full-stack/index.json b/docs/pt-br/ciclo-de-vida-full-stack/index.json deleted file mode 100644 index ab7261fc..00000000 --- a/docs/pt-br/ciclo-de-vida-full-stack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Ciclo de Vida Full-Stack","html":"

Métodos de ciclo de vida são funções nomeadas de forma especial que você pode declarar na classe.

\n

Cada método de ciclo de vida roda em uma fila de ordem específica, garantindo que todos os componentes do ciclo atual sejam preparados antes do primeiro ser iniciado.

\n

Prepare

Esse método é bloqueante e roda antes da primeira renderização do componente.

\n

Você pode usar essa função para definir o estado que o usuário verá antes do carregamento.

\n

Se o usuário estiver entrando através dessa rota, prepare irá rodar no servidor antes do Nullstack renderizar sua aplicação no lado do servidor.

\n

Se o usuário estiver navegando por outra rota, esse método rodará no cliente.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  prepare() {\n    this.date = new Date();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Initiate

Esse método pode ser assíncrono, e roda assim que o componente for preparado e renderizado pela primeira vez.

\n

Você pode usá-lo para invocar outra função do servidor e carregar os dados para apresentar a página.

\n

Se o usuário estiver entrando através dessa rota, initiate rodará no servidor.

\n

Nullstack irá esperar até que a promise seja resolvida e então finalmente irá gerar o HTML que será servido.

\n

Se o usuário estiver navegando por outra rota, esse método rodará no cliente.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.task = await getTaskByDay({\n      day: this.date\n    });\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

✨ Aprenda mais sobre funções do servidor.

\n
\n

Hydrate

Esse método é assíncrono e rodará apenas no cliente.

\n

Ele sempre rodará independente do ambiente que iniciou o componente.

\n

Esse é um bom lugar para acionar dependências que manipulam o DOM ou que podem rodar apenas no lado do cliente.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async hydrate() {\n    this.timer = setInterval(() => {\n      console.log(this.date);\n    }, 1000);\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Update

Esse método é assíncrono e rodará apenas no cliente.

\n

Ele roda em todos os componentes sempre que o estado da aplicação mudar.

\n
\n

🔥 Tome cuidado para não causar loops infinitos quando mutacionar o estado dentro de update.

\n
\n

Ele irá rodar logo antes da renderização, mas não irá bloquear a fila.

\n

A função update não rodará até que a aplicação seja renderizada após initiate.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async update() {\n    const today = new Date();\n    if(today.getDay() != this.date.getDay()) {\n      this.date = today;\n      await this.initiate();\n    }\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

✨ Métodos de ciclo de vida não têm efeitos colaterais, você pode chamá-los manualmentes sem causar problemas.

\n
\n

Terminate

Esse método é assíncrono e rodará apenas no cliente.

\n

Ele irá rodar após o componente deixar o DOM.

\n

Esse é o lugar para limpar qualquer coisa que você definiu no método hydrate.

\n

Essa instância será levada pelo garbage collector após a resolução da Promise.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async terminate() {\n    clearInterval(this.timer);\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Próximos passos

⚔ Aprenda sobre funções do servidor.

\n","description":"Métodos de ciclo de vida são funções nomeadas de forma especial que você pode declarar na classe"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Ciclo de Vida Full-Stack - Nullstack","description":"Métodos de ciclo de vida são funções nomeadas de forma especial que você pode declarar na classe"}} \ No newline at end of file diff --git a/docs/pt-br/comecando.html b/docs/pt-br/comecando.html deleted file mode 100644 index 9d971fc4..00000000 --- a/docs/pt-br/comecando.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - Começando - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Começando

-

📌 Você pode assistir um tutorial no nosso Canal do Youtube.

-
-

Crie aplicações javascript full-stack em segundos usando npx para gerar os arquivos do seu projeto usando o template mais recente.

-
-

🔥 A versão mínima necessária do node.js para o modo de desenvovimento é 12.12.0.

-
-
-

⚠ Se o diretório em que você está contém espaços, você usa Windows e o npx der erros, leia sobre o bug conhecido do npx.

-
-

Troque project-name com o nome do seu projeto e rode o comanto abaixo para começar um projeto:

-
npx create-nullstack-app project-name
-
-

Troque o diretório para a pasta gerada:

-
cd project-name
-
-

Instale as dependências:

-
npm install
-
-

Inicie a aplicação em modo de desenvolvimento:

-
npm start
-
-

Entendendo os arquivos gerados

As seguintes pastas e arquivos serão gerados:

-

index.js

Este é o ponto de entrada do Webpack.

-

Normalmente, você não precisará mexer neste arquivo, mas é um lugar conveniente para importar dependências globais como frameworks CSS.

-

src/

Esta pasta contêm o código fonte da sua aplicação.

-

src/Application.njs

Este é o arquivo principal da sua aplicação.

-
-

✨ Saiba mais sobre a extensão de arquivo njs.

-
-

A função start será automaticamente chamada uma vez que você rode npm start, use a para preencher o contexto do seu servidor com coisas como banco de dados, configurações, e segredos.

-
-

✨ Saiba mais sobre a inicialização da aplicação.

-
-

src/Application.scss

Este é um arquivo vazio só para demonstrar que você pode usar SCSS com Nullstack.

-

É uma boa prática importar um arquivo de estilo em um componente com o mesmo nome.

-
-

✨ Saiba mais sobre estilos.

-
-

public/

Todo arquivo aqui ficará disponível para qualquer um na raíz do domínio.

-

Por padrão create-nullstack-app gera os ícones necessários para o seu manifest.json e imagens para meta tags OG.

-
-

✨ Saiba mais sobre o manifest.json.

-
-

Tenha certeza de trocar estas imagens pela identidade do seu projeto.

-

.development/

Este é o resultado compilado da sua aplicação em modo de desenvolvimento.

-
-

🔥 Não toque nesta pasta

-
-

.production/

Este é o resultado compilado da sua aplicação em modo de produção.

-
-

🔥 Não toque nesta pasta

-
-
-

✨ Saiba mais sobre como fazer deploy de aplicação Nullstack.

-
-

Bug conhecido do npx

Avisado em issues do npx como #100, #110 e #143, ele tem um erro ao tentar resolver o caminho para sua pasta de cache quando este contém espaços.

-

Se isso ocorrer com você, nossas recomendações são:

-
    -
  • Usando baixado como normalmente faria com npm:

    -
    npm i -g create-nullstack-app
    -create-nullstack-app project-name
    -
  • -
  • ou, mudar o diretório da pasta de cache, como dito aqui e aqui:

    -
      -
    • Se deseja manter o uso do espaço, subtitua PrimeiroNome pelo usado no seu caminho e rode:
    • -
    -
    npm config set cache "C:\Users\PrimeiroNome~1\AppData\Roaming\npm-cache" --global
    -
    -
      -
    • ou, usando outro caminho sem espaços:
    • -
    -
    npm config set cache C:\tmp\nodejs\npm-cache --global
    -
  • -
-

Próximo Passo

⚔ Crie seu primeiro componente renderizável.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/comecando/index.html b/docs/pt-br/comecando/index.html deleted file mode 100644 index 9d971fc4..00000000 --- a/docs/pt-br/comecando/index.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - Começando - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Começando

-

📌 Você pode assistir um tutorial no nosso Canal do Youtube.

-
-

Crie aplicações javascript full-stack em segundos usando npx para gerar os arquivos do seu projeto usando o template mais recente.

-
-

🔥 A versão mínima necessária do node.js para o modo de desenvovimento é 12.12.0.

-
-
-

⚠ Se o diretório em que você está contém espaços, você usa Windows e o npx der erros, leia sobre o bug conhecido do npx.

-
-

Troque project-name com o nome do seu projeto e rode o comanto abaixo para começar um projeto:

-
npx create-nullstack-app project-name
-
-

Troque o diretório para a pasta gerada:

-
cd project-name
-
-

Instale as dependências:

-
npm install
-
-

Inicie a aplicação em modo de desenvolvimento:

-
npm start
-
-

Entendendo os arquivos gerados

As seguintes pastas e arquivos serão gerados:

-

index.js

Este é o ponto de entrada do Webpack.

-

Normalmente, você não precisará mexer neste arquivo, mas é um lugar conveniente para importar dependências globais como frameworks CSS.

-

src/

Esta pasta contêm o código fonte da sua aplicação.

-

src/Application.njs

Este é o arquivo principal da sua aplicação.

-
-

✨ Saiba mais sobre a extensão de arquivo njs.

-
-

A função start será automaticamente chamada uma vez que você rode npm start, use a para preencher o contexto do seu servidor com coisas como banco de dados, configurações, e segredos.

-
-

✨ Saiba mais sobre a inicialização da aplicação.

-
-

src/Application.scss

Este é um arquivo vazio só para demonstrar que você pode usar SCSS com Nullstack.

-

É uma boa prática importar um arquivo de estilo em um componente com o mesmo nome.

-
-

✨ Saiba mais sobre estilos.

-
-

public/

Todo arquivo aqui ficará disponível para qualquer um na raíz do domínio.

-

Por padrão create-nullstack-app gera os ícones necessários para o seu manifest.json e imagens para meta tags OG.

-
-

✨ Saiba mais sobre o manifest.json.

-
-

Tenha certeza de trocar estas imagens pela identidade do seu projeto.

-

.development/

Este é o resultado compilado da sua aplicação em modo de desenvolvimento.

-
-

🔥 Não toque nesta pasta

-
-

.production/

Este é o resultado compilado da sua aplicação em modo de produção.

-
-

🔥 Não toque nesta pasta

-
-
-

✨ Saiba mais sobre como fazer deploy de aplicação Nullstack.

-
-

Bug conhecido do npx

Avisado em issues do npx como #100, #110 e #143, ele tem um erro ao tentar resolver o caminho para sua pasta de cache quando este contém espaços.

-

Se isso ocorrer com você, nossas recomendações são:

-
    -
  • Usando baixado como normalmente faria com npm:

    -
    npm i -g create-nullstack-app
    -create-nullstack-app project-name
    -
  • -
  • ou, mudar o diretório da pasta de cache, como dito aqui e aqui:

    -
      -
    • Se deseja manter o uso do espaço, subtitua PrimeiroNome pelo usado no seu caminho e rode:
    • -
    -
    npm config set cache "C:\Users\PrimeiroNome~1\AppData\Roaming\npm-cache" --global
    -
    -
      -
    • ou, usando outro caminho sem espaços:
    • -
    -
    npm config set cache C:\tmp\nodejs\npm-cache --global
    -
  • -
-

Próximo Passo

⚔ Crie seu primeiro componente renderizável.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/comecando/index.json b/docs/pt-br/comecando/index.json deleted file mode 100644 index 410e625e..00000000 --- a/docs/pt-br/comecando/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Começando","html":"
\n

📌 Você pode assistir um tutorial no nosso Canal do Youtube.

\n
\n

Crie aplicações javascript full-stack em segundos usando npx para gerar os arquivos do seu projeto usando o template mais recente.

\n
\n

🔥 A versão mínima necessária do node.js para o modo de desenvovimento é 12.12.0.

\n
\n
\n

⚠ Se o diretório em que você está contém espaços, você usa Windows e o npx der erros, leia sobre o bug conhecido do npx.

\n
\n

Troque project-name com o nome do seu projeto e rode o comanto abaixo para começar um projeto:

\n
npx create-nullstack-app project-name\n
\n

Troque o diretório para a pasta gerada:

\n
cd project-name\n
\n

Instale as dependências:

\n
npm install\n
\n

Inicie a aplicação em modo de desenvolvimento:

\n
npm start\n
\n

Entendendo os arquivos gerados

As seguintes pastas e arquivos serão gerados:

\n

index.js

Este é o ponto de entrada do Webpack.

\n

Normalmente, você não precisará mexer neste arquivo, mas é um lugar conveniente para importar dependências globais como frameworks CSS.

\n

src/

Esta pasta contêm o código fonte da sua aplicação.

\n

src/Application.njs

Este é o arquivo principal da sua aplicação.

\n
\n

✨ Saiba mais sobre a extensão de arquivo njs.

\n
\n

A função start será automaticamente chamada uma vez que você rode npm start, use a para preencher o contexto do seu servidor com coisas como banco de dados, configurações, e segredos.

\n
\n

✨ Saiba mais sobre a inicialização da aplicação.

\n
\n

src/Application.scss

Este é um arquivo vazio só para demonstrar que você pode usar SCSS com Nullstack.

\n

É uma boa prática importar um arquivo de estilo em um componente com o mesmo nome.

\n
\n

✨ Saiba mais sobre estilos.

\n
\n

public/

Todo arquivo aqui ficará disponível para qualquer um na raíz do domínio.

\n

Por padrão create-nullstack-app gera os ícones necessários para o seu manifest.json e imagens para meta tags OG.

\n
\n

✨ Saiba mais sobre o manifest.json.

\n
\n

Tenha certeza de trocar estas imagens pela identidade do seu projeto.

\n

.development/

Este é o resultado compilado da sua aplicação em modo de desenvolvimento.

\n
\n

🔥 Não toque nesta pasta

\n
\n

.production/

Este é o resultado compilado da sua aplicação em modo de produção.

\n
\n

🔥 Não toque nesta pasta

\n
\n
\n

✨ Saiba mais sobre como fazer deploy de aplicação Nullstack.

\n
\n

Bug conhecido do npx

Avisado em issues do npx como #100, #110 e #143, ele tem um erro ao tentar resolver o caminho para sua pasta de cache quando este contém espaços.

\n

Se isso ocorrer com você, nossas recomendações são:

\n
    \n
  • Usando baixado como normalmente faria com npm:

    \n
    npm i -g create-nullstack-app\ncreate-nullstack-app project-name\n
  • \n
  • ou, mudar o diretório da pasta de cache, como dito aqui e aqui:

    \n
      \n
    • Se deseja manter o uso do espaço, subtitua PrimeiroNome pelo usado no seu caminho e rode:
    • \n
    \n
    npm config set cache \"C:\\Users\\PrimeiroNome~1\\AppData\\Roaming\\npm-cache\" --global\n
    \n
      \n
    • ou, usando outro caminho sem espaços:
    • \n
    \n
    npm config set cache C:\\tmp\\nodejs\\npm-cache --global\n
  • \n
\n

Próximo Passo

⚔ Crie seu primeiro componente renderizável.

\n","description":"Crie aplicações full-stack em javascript em meros segundos"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Começando - Nullstack","description":"Crie aplicações full-stack em javascript em meros segundos"}} \ No newline at end of file diff --git a/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack.html b/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack.html deleted file mode 100644 index 8026ef0a..00000000 --- a/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Como fazer Deploy - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Como fazer Deploy

Com o Nullstack é fácil ter sua aplicação instalada e funcionando no modo de produção

-
-

🐱‍💻 stonks

-
-

Nullstack compila seu código e todas as suas dependências usando Webpack.

-

A saída da compilação é movida para a pasta .production e é a única pasta além de public que precisa ser movida para a máquina host.

-

Se você tiver project.cdn definido, deverá mover a pasta public para o cdn real.

-
-

💡 É importante que a pasta .production esteja presente para a detecção do ambiente

-
-

A máquina host deve ter pelo menos a versão 8.10.0 do node instalada.

-

Você não precisa executar "npm install" na máquina host.

-
-

✨ Você pode configurar o ambiente usando settings e secrets

-
-

Para iniciar o servidor, basta executar:

-
node .production/server.js
-
-
-

✨ Recomenda-se o uso de um gerenciador de processos como PM2

-
-

Como fazer o Deploy de um site estático gerado com NullStack

Depois de gerar um site estático, tudo o que você precisa fazer é mover a pasta de saída para qualquer máquina host capaz de servir HTML.

-

Próxima Etapa

-

🎉 Parabéns. Você concluiu os conceitos avançados!

-
-

⚔ Aprenda como usar MongoDB com Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack/index.html b/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack/index.html deleted file mode 100644 index 8026ef0a..00000000 --- a/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Como fazer Deploy - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Como fazer Deploy

Com o Nullstack é fácil ter sua aplicação instalada e funcionando no modo de produção

-
-

🐱‍💻 stonks

-
-

Nullstack compila seu código e todas as suas dependências usando Webpack.

-

A saída da compilação é movida para a pasta .production e é a única pasta além de public que precisa ser movida para a máquina host.

-

Se você tiver project.cdn definido, deverá mover a pasta public para o cdn real.

-
-

💡 É importante que a pasta .production esteja presente para a detecção do ambiente

-
-

A máquina host deve ter pelo menos a versão 8.10.0 do node instalada.

-

Você não precisa executar "npm install" na máquina host.

-
-

✨ Você pode configurar o ambiente usando settings e secrets

-
-

Para iniciar o servidor, basta executar:

-
node .production/server.js
-
-
-

✨ Recomenda-se o uso de um gerenciador de processos como PM2

-
-

Como fazer o Deploy de um site estático gerado com NullStack

Depois de gerar um site estático, tudo o que você precisa fazer é mover a pasta de saída para qualquer máquina host capaz de servir HTML.

-

Próxima Etapa

-

🎉 Parabéns. Você concluiu os conceitos avançados!

-
-

⚔ Aprenda como usar MongoDB com Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack/index.json b/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack/index.json deleted file mode 100644 index 39f1732e..00000000 --- a/docs/pt-br/como-fazer-deploy-de-aplicacao-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Como fazer Deploy","html":"

Com o Nullstack é fácil ter sua aplicação instalada e funcionando no modo de produção

\n
\n

🐱‍💻 stonks

\n
\n

Nullstack compila seu código e todas as suas dependências usando Webpack.

\n

A saída da compilação é movida para a pasta .production e é a única pasta além de public que precisa ser movida para a máquina host.

\n

Se você tiver project.cdn definido, deverá mover a pasta public para o cdn real.

\n
\n

💡 É importante que a pasta .production esteja presente para a detecção do ambiente

\n
\n

A máquina host deve ter pelo menos a versão 8.10.0 do node instalada.

\n

Você não precisa executar "npm install" na máquina host.

\n
\n

✨ Você pode configurar o ambiente usando settings e secrets

\n
\n

Para iniciar o servidor, basta executar:

\n
node .production/server.js\n
\n
\n

✨ Recomenda-se o uso de um gerenciador de processos como PM2

\n
\n

Como fazer o Deploy de um site estático gerado com NullStack

Depois de gerar um site estático, tudo o que você precisa fazer é mover a pasta de saída para qualquer máquina host capaz de servir HTML.

\n

Próxima Etapa

\n

🎉 Parabéns. Você concluiu os conceitos avançados!

\n
\n

⚔ Aprenda como usar MongoDB com Nullstack.

\n","description":"Com o Nullstack é fácil ter sua aplicação instalada e funcionando no modo de produção"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Como fazer Deploy - Nullstack","description":"Com o Nullstack é fácil ter sua aplicação instalada e funcionando no modo de produção"}} \ No newline at end of file diff --git a/docs/pt-br/como-usar-facebook-pixel-no-nullstack.html b/docs/pt-br/como-usar-facebook-pixel-no-nullstack.html deleted file mode 100644 index 6ce18d1d..00000000 --- a/docs/pt-br/como-usar-facebook-pixel-no-nullstack.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - Facebook Pixel - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Facebook Pixel

De acordo com developers.facebook.com:

-

"O Facebook Pixel é um trecho de código JavaScript que permite rastrear a atividade do visitante em seu site."

-

Você pode aproveitar as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos Pixel dinamicamente.

-

O Facebook Pixel só pode ser chamado depois de hydrate para garantir que está sendo executado no cliente.

-
import Nullstack from 'nullstack';
-
-class FacebookPixel extends Nullstack {
-
-  async hydrate({page, id}) {
-    ! function(f, b, e, v, n, t, s) {
-      if (f.fbq) return;
-      n = f.fbq = function() {
-          n.callMethod ?
-              n.callMethod.apply(n, arguments) : n.queue.push(arguments)
-      };
-      if (!f._fbq) f._fbq = n;
-      n.push = n;
-      n.loaded = !0;
-      n.version = '2.0';
-      n.queue = [];
-      t = b.createElement(e);
-      t.async = !0;
-      t.src = v;
-      s = b.getElementsByTagName(e)[0];
-      s.parentNode.insertBefore(t, s)
-    }(window, document, 'script',
-      'https://connect.facebook.net/en_US/fbevents.js');
-    fbq('init', id);
-    fbq('track', 'PageView');
-    window.addEventListener(page.event, () => {
-      fbq('init', id);
-      fbq('track', 'PageView');
-    })
-  }
-}
-
-export default FacebookPixel;
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from './FacebookPixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="SUBSTITUA_COM_SEU_ID_DO_FACEBOOK_PIXEL" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Usando um Wrapper

Alternativamente, você pode instalar nullstack-facebook-pixel como uma dependência:

-
npm install nullstack-facebook-pixel
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from 'nullstack-facebook-pixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="SUBSTITUA_COM_SEU_ID_DO_FACEBOOK_PIXEL" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Próximo Passo

-

🎉 Parabéns. Você concluiu a documentação!

-
-

⚔ Se você deseja ver mais exemplos aqui, abra uma issue no github.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-usar-facebook-pixel-no-nullstack/index.html b/docs/pt-br/como-usar-facebook-pixel-no-nullstack/index.html deleted file mode 100644 index 6ce18d1d..00000000 --- a/docs/pt-br/como-usar-facebook-pixel-no-nullstack/index.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - Facebook Pixel - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Facebook Pixel

De acordo com developers.facebook.com:

-

"O Facebook Pixel é um trecho de código JavaScript que permite rastrear a atividade do visitante em seu site."

-

Você pode aproveitar as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos Pixel dinamicamente.

-

O Facebook Pixel só pode ser chamado depois de hydrate para garantir que está sendo executado no cliente.

-
import Nullstack from 'nullstack';
-
-class FacebookPixel extends Nullstack {
-
-  async hydrate({page, id}) {
-    ! function(f, b, e, v, n, t, s) {
-      if (f.fbq) return;
-      n = f.fbq = function() {
-          n.callMethod ?
-              n.callMethod.apply(n, arguments) : n.queue.push(arguments)
-      };
-      if (!f._fbq) f._fbq = n;
-      n.push = n;
-      n.loaded = !0;
-      n.version = '2.0';
-      n.queue = [];
-      t = b.createElement(e);
-      t.async = !0;
-      t.src = v;
-      s = b.getElementsByTagName(e)[0];
-      s.parentNode.insertBefore(t, s)
-    }(window, document, 'script',
-      'https://connect.facebook.net/en_US/fbevents.js');
-    fbq('init', id);
-    fbq('track', 'PageView');
-    window.addEventListener(page.event, () => {
-      fbq('init', id);
-      fbq('track', 'PageView');
-    })
-  }
-}
-
-export default FacebookPixel;
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from './FacebookPixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="SUBSTITUA_COM_SEU_ID_DO_FACEBOOK_PIXEL" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Usando um Wrapper

Alternativamente, você pode instalar nullstack-facebook-pixel como uma dependência:

-
npm install nullstack-facebook-pixel
-
-
import Nullstack from 'nullstack';
-import FacebookPixel from 'nullstack-facebook-pixel';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <FacebookPixel id="SUBSTITUA_COM_SEU_ID_DO_FACEBOOK_PIXEL" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Próximo Passo

-

🎉 Parabéns. Você concluiu a documentação!

-
-

⚔ Se você deseja ver mais exemplos aqui, abra uma issue no github.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-usar-facebook-pixel-no-nullstack/index.json b/docs/pt-br/como-usar-facebook-pixel-no-nullstack/index.json deleted file mode 100644 index 734b7342..00000000 --- a/docs/pt-br/como-usar-facebook-pixel-no-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Facebook Pixel","html":"

De acordo com developers.facebook.com:

\n

"O Facebook Pixel é um trecho de código JavaScript que permite rastrear a atividade do visitante em seu site."

\n

Você pode aproveitar as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos Pixel dinamicamente.

\n

O Facebook Pixel só pode ser chamado depois de hydrate para garantir que está sendo executado no cliente.

\n
import Nullstack from 'nullstack';\n\nclass FacebookPixel extends Nullstack {\n\n  async hydrate({page, id}) {\n    ! function(f, b, e, v, n, t, s) {\n      if (f.fbq) return;\n      n = f.fbq = function() {\n          n.callMethod ?\n              n.callMethod.apply(n, arguments) : n.queue.push(arguments)\n      };\n      if (!f._fbq) f._fbq = n;\n      n.push = n;\n      n.loaded = !0;\n      n.version = '2.0';\n      n.queue = [];\n      t = b.createElement(e);\n      t.async = !0;\n      t.src = v;\n      s = b.getElementsByTagName(e)[0];\n      s.parentNode.insertBefore(t, s)\n    }(window, document, 'script',\n      'https://connect.facebook.net/en_US/fbevents.js');\n    fbq('init', id);\n    fbq('track', 'PageView');\n    window.addEventListener(page.event, () => {\n      fbq('init', id);\n      fbq('track', 'PageView');\n    })\n  }\n}\n\nexport default FacebookPixel;\n
\n
import Nullstack from 'nullstack';\nimport FacebookPixel from './FacebookPixel';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <FacebookPixel id=\"SUBSTITUA_COM_SEU_ID_DO_FACEBOOK_PIXEL\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Usando um Wrapper

Alternativamente, você pode instalar nullstack-facebook-pixel como uma dependência:

\n
npm install nullstack-facebook-pixel\n
\n
import Nullstack from 'nullstack';\nimport FacebookPixel from 'nullstack-facebook-pixel';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <FacebookPixel id=\"SUBSTITUA_COM_SEU_ID_DO_FACEBOOK_PIXEL\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Próximo Passo

\n

🎉 Parabéns. Você concluiu a documentação!

\n
\n

⚔ Se você deseja ver mais exemplos aqui, abra uma issue no github.

\n","description":"Aproveite as vantagens do [contexto](/pt-br/contexto) e [eventos personalizados](/pt-br/contexto-page) para criar um componente que envia eventos Pixel dinamicamente."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Facebook Pixel - Nullstack","description":"Aproveite as vantagens do [contexto](/pt-br/contexto) e [eventos personalizados](/pt-br/contexto-page) para criar um componente que envia eventos Pixel dinamicamente."}} \ No newline at end of file diff --git a/docs/pt-br/como-usar-google-analytics-no-nullstack.html b/docs/pt-br/como-usar-google-analytics-no-nullstack.html deleted file mode 100644 index 1c9f26d4..00000000 --- a/docs/pt-br/como-usar-google-analytics-no-nullstack.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - Google Analytics - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Google Analytics

De acordo com analytics.google.com:

-

"O Google Analytics permite que você avalie o ROI de publicidade, bem como rastreie o Flash, vídeo e mídias sociais em sites e aplicativos."

-

Você pode aproveitar as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos GTAG dinamicamente.

-

O GTAG só pode ser chamado depois de hydrate para garantir que está sendo executado no cliente.

-
import Nullstack from 'nullstack';
-
-class GoogleAnalytics extends Nullstack {
-
-  hydrate({router, page, id}) {
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){
-      dataLayer.push(arguments);
-    }
-    gtag('js', new Date());
-    gtag('config', id, {
-      page_title: page.title,
-      page_path: router.url
-    });
-    window.addEventListener(page.event, () => {
-      gtag('event', 'page_view', {
-        page_title: page.title,
-        page_path: router.url
-      })
-    })
-  }
-  
-  render({id}) {
-    return (
-      <script 
-        async
-        src={`https://www.googletagmanager.com/gtag/js?id=${id}`}
-      />
-    )
-  }
-
-}
-
-export default GoogleAnalytics;
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from './GoogleAnalytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="SUBSTITUA_COM_SEU_ID_DO_GOOGLE_ANALYTICS" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Usando um Wrapper

Alternativamente, você pode instalar o nullstack-google-analytics como uma dependência:

-
npm install nullstack-google-analytics
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from 'nullstack-google-analytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="SUBSTITUA_COM_SEU_ID_DO_GOOGLE_ANALYTICS" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Próximo Passo

⚔ Aprenda como usar o Facebook Pixel com o Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-usar-google-analytics-no-nullstack/index.html b/docs/pt-br/como-usar-google-analytics-no-nullstack/index.html deleted file mode 100644 index 1c9f26d4..00000000 --- a/docs/pt-br/como-usar-google-analytics-no-nullstack/index.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - Google Analytics - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Google Analytics

De acordo com analytics.google.com:

-

"O Google Analytics permite que você avalie o ROI de publicidade, bem como rastreie o Flash, vídeo e mídias sociais em sites e aplicativos."

-

Você pode aproveitar as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos GTAG dinamicamente.

-

O GTAG só pode ser chamado depois de hydrate para garantir que está sendo executado no cliente.

-
import Nullstack from 'nullstack';
-
-class GoogleAnalytics extends Nullstack {
-
-  hydrate({router, page, id}) {
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){
-      dataLayer.push(arguments);
-    }
-    gtag('js', new Date());
-    gtag('config', id, {
-      page_title: page.title,
-      page_path: router.url
-    });
-    window.addEventListener(page.event, () => {
-      gtag('event', 'page_view', {
-        page_title: page.title,
-        page_path: router.url
-      })
-    })
-  }
-  
-  render({id}) {
-    return (
-      <script 
-        async
-        src={`https://www.googletagmanager.com/gtag/js?id=${id}`}
-      />
-    )
-  }
-
-}
-
-export default GoogleAnalytics;
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from './GoogleAnalytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="SUBSTITUA_COM_SEU_ID_DO_GOOGLE_ANALYTICS" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Usando um Wrapper

Alternativamente, você pode instalar o nullstack-google-analytics como uma dependência:

-
npm install nullstack-google-analytics
-
-
import Nullstack from 'nullstack';
-import GoogleAnalytics from 'nullstack-google-analytics';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <GoogleAnalytics id="SUBSTITUA_COM_SEU_ID_DO_GOOGLE_ANALYTICS" />
-      </main>
-    )
-  }
-
-
-}
-
-export default Application;
-
-

Próximo Passo

⚔ Aprenda como usar o Facebook Pixel com o Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-usar-google-analytics-no-nullstack/index.json b/docs/pt-br/como-usar-google-analytics-no-nullstack/index.json deleted file mode 100644 index f187910f..00000000 --- a/docs/pt-br/como-usar-google-analytics-no-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Google Analytics","html":"

De acordo com analytics.google.com:

\n

"O Google Analytics permite que você avalie o ROI de publicidade, bem como rastreie o Flash, vídeo e mídias sociais em sites e aplicativos."

\n

Você pode aproveitar as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos GTAG dinamicamente.

\n

O GTAG só pode ser chamado depois de hydrate para garantir que está sendo executado no cliente.

\n
import Nullstack from 'nullstack';\n\nclass GoogleAnalytics extends Nullstack {\n\n  hydrate({router, page, id}) {\n    window.dataLayer = window.dataLayer || [];\n    function gtag(){\n      dataLayer.push(arguments);\n    }\n    gtag('js', new Date());\n    gtag('config', id, {\n      page_title: page.title,\n      page_path: router.url\n    });\n    window.addEventListener(page.event, () => {\n      gtag('event', 'page_view', {\n        page_title: page.title,\n        page_path: router.url\n      })\n    })\n  }\n  \n  render({id}) {\n    return (\n      <script \n        async\n        src={`https://www.googletagmanager.com/gtag/js?id=${id}`}\n      />\n    )\n  }\n\n}\n\nexport default GoogleAnalytics;\n
\n
import Nullstack from 'nullstack';\nimport GoogleAnalytics from './GoogleAnalytics';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <GoogleAnalytics id=\"SUBSTITUA_COM_SEU_ID_DO_GOOGLE_ANALYTICS\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Usando um Wrapper

Alternativamente, você pode instalar o nullstack-google-analytics como uma dependência:

\n
npm install nullstack-google-analytics\n
\n
import Nullstack from 'nullstack';\nimport GoogleAnalytics from 'nullstack-google-analytics';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <GoogleAnalytics id=\"SUBSTITUA_COM_SEU_ID_DO_GOOGLE_ANALYTICS\" />\n      </main>\n    )\n  }\n\n\n}\n\nexport default Application;\n
\n

Próximo Passo

⚔ Aprenda como usar o Facebook Pixel com o Nullstack.

\n","description":"Aproveite as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos GTAG dinamicamente."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Google Analytics - Nullstack","description":"Aproveite as vantagens do contexto e dos eventos personalizados para criar um componente que envia eventos GTAG dinamicamente."}} \ No newline at end of file diff --git a/docs/pt-br/como-usar-mongodb-com-nullstack.html b/docs/pt-br/como-usar-mongodb-com-nullstack.html deleted file mode 100644 index 4fb3f74e..00000000 --- a/docs/pt-br/como-usar-mongodb-com-nullstack.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - Como usar MongoDB - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Como usar MongoDB

De acordo com mongodb.com:

-

"O MongoDB é um banco de dados distribuído de propósito geral, baseado em documentos, criado para desenvolvedores de aplicativos modernos e para a era da nuvem."

-

Você pode usar qualquer banco de dados com Nullstack, mas a integração javascript e flexibilidade do MongoDB parece especialmente boa com aplicativos Nullstack.

-

Instale o driver MongoDB do npm:

-
npm install mongodb
-
-

Configure as credenciais do banco de dados usando secrets.

-

O último passo é simplesmente atribuir a conexão do banco de dados ao contexto do servidor.

-
import Nullstack from 'nullstack';
-import {MongoClient} from 'mongodb';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    const {secrets} = context;
-    secrets.development.databaseHost = 'mongodb://localhost:27017/dbname';
-    secrets.databaseName = 'dbname';
-    await this.startDatabase(context);
-  }
-
-  static async startDatabase(context) {
-    const {secrets} = context;
-    const databaseClient = new MongoClient(secrets.databaseHost);
-    await databaseClient.connect();
-    context.database = await databaseClient.db(secrets.databaseName);
-  }
-
-}
-
-export default Application;
-
-

O exemplo acima tornará a chave database disponível para todas as funções do servidor.

-
import Nullstack from 'nullstack';
-
-class BooksList extends Nullstack {
-
-  books = [];
-
-  static async getBooks({database}) {
-    return await database.collection('books').find().toArray();
-  }
-
-  async initiate() {
-    this.books = await this.getBooks();
-  }
-
-  // ...
-
-}
-
-export default BooksList;
-
-

Próximo Passo

⚔ Aprenda como usar Google Analytics no Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-usar-mongodb-com-nullstack/index.html b/docs/pt-br/como-usar-mongodb-com-nullstack/index.html deleted file mode 100644 index 4fb3f74e..00000000 --- a/docs/pt-br/como-usar-mongodb-com-nullstack/index.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - Como usar MongoDB - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Como usar MongoDB

De acordo com mongodb.com:

-

"O MongoDB é um banco de dados distribuído de propósito geral, baseado em documentos, criado para desenvolvedores de aplicativos modernos e para a era da nuvem."

-

Você pode usar qualquer banco de dados com Nullstack, mas a integração javascript e flexibilidade do MongoDB parece especialmente boa com aplicativos Nullstack.

-

Instale o driver MongoDB do npm:

-
npm install mongodb
-
-

Configure as credenciais do banco de dados usando secrets.

-

O último passo é simplesmente atribuir a conexão do banco de dados ao contexto do servidor.

-
import Nullstack from 'nullstack';
-import {MongoClient} from 'mongodb';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    const {secrets} = context;
-    secrets.development.databaseHost = 'mongodb://localhost:27017/dbname';
-    secrets.databaseName = 'dbname';
-    await this.startDatabase(context);
-  }
-
-  static async startDatabase(context) {
-    const {secrets} = context;
-    const databaseClient = new MongoClient(secrets.databaseHost);
-    await databaseClient.connect();
-    context.database = await databaseClient.db(secrets.databaseName);
-  }
-
-}
-
-export default Application;
-
-

O exemplo acima tornará a chave database disponível para todas as funções do servidor.

-
import Nullstack from 'nullstack';
-
-class BooksList extends Nullstack {
-
-  books = [];
-
-  static async getBooks({database}) {
-    return await database.collection('books').find().toArray();
-  }
-
-  async initiate() {
-    this.books = await this.getBooks();
-  }
-
-  // ...
-
-}
-
-export default BooksList;
-
-

Próximo Passo

⚔ Aprenda como usar Google Analytics no Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/como-usar-mongodb-com-nullstack/index.json b/docs/pt-br/como-usar-mongodb-com-nullstack/index.json deleted file mode 100644 index 3c6b25f4..00000000 --- a/docs/pt-br/como-usar-mongodb-com-nullstack/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Como usar MongoDB","html":"

De acordo com mongodb.com:

\n

"O MongoDB é um banco de dados distribuído de propósito geral, baseado em documentos, criado para desenvolvedores de aplicativos modernos e para a era da nuvem."

\n

Você pode usar qualquer banco de dados com Nullstack, mas a integração javascript e flexibilidade do MongoDB parece especialmente boa com aplicativos Nullstack.

\n

Instale o driver MongoDB do npm:

\n
npm install mongodb\n
\n

Configure as credenciais do banco de dados usando secrets.

\n

O último passo é simplesmente atribuir a conexão do banco de dados ao contexto do servidor.

\n
import Nullstack from 'nullstack';\nimport {MongoClient} from 'mongodb';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    const {secrets} = context;\n    secrets.development.databaseHost = 'mongodb://localhost:27017/dbname';\n    secrets.databaseName = 'dbname';\n    await this.startDatabase(context);\n  }\n\n  static async startDatabase(context) {\n    const {secrets} = context;\n    const databaseClient = new MongoClient(secrets.databaseHost);\n    await databaseClient.connect();\n    context.database = await databaseClient.db(secrets.databaseName);\n  }\n\n}\n\nexport default Application;\n
\n

O exemplo acima tornará a chave database disponível para todas as funções do servidor.

\n
import Nullstack from 'nullstack';\n\nclass BooksList extends Nullstack {\n\n  books = [];\n\n  static async getBooks({database}) {\n    return await database.collection('books').find().toArray();\n  }\n\n  async initiate() {\n    this.books = await this.getBooks();\n  }\n\n  // ...\n\n}\n\nexport default BooksList;\n
\n

Próximo Passo

⚔ Aprenda como usar Google Analytics no Nullstack.

\n","description":"Você pode usar qualquer banco de dados com Nullstack, mas a integração javascript e flexibilidade do MongoDB parece especialmente boa com aplicativos Nullstack"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Como usar MongoDB - Nullstack","description":"Você pode usar qualquer banco de dados com Nullstack, mas a integração javascript e flexibilidade do MongoDB parece especialmente boa com aplicativos Nullstack"}} \ No newline at end of file diff --git a/docs/pt-br/componentes-com-estado.html b/docs/pt-br/componentes-com-estado.html deleted file mode 100644 index e4eada75..00000000 --- a/docs/pt-br/componentes-com-estado.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - Componentes com estado - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes com estado

Um framework web full-stack produtivo não deve forçar você a pensar sobre detalhes de estrutura.

-

Nullstack assume o controle de suas subclasses e gera um proxy para cada instância.

-

Quando você invoca qualquer coisa em sua classe, você está na verdade dizendo ao Nullstack o que fazer com o ambiente nos bastidores.

-

Isso permite que você use operações de javascript vanilla como atribuir a uma variável e ver o reflexo no dom.

-

Mutabilidade

Você pode modificar variáveis ​​de instância para atualizar o estado do seu aplicativo.

-

As funções são vinculadas automaticamente ao proxy da instância e podem ser passadas como referência para eventos.

-

Os eventos são declarados como atributos HTML normais.

-
import Nullstack from "nullstack";
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment() {
-    this.count++;
-  }
-
-  render() {
-    return (
-      <button onclick={this.increment}>
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 As atualizações são feitas em lotes, geralmente enquanto aguardam chamadas assíncronas, portanto, fazer várias atribuições não tem custos de desempenho!

-
-

Objeto de Eventos

Você pode criar atalho em eventos que são simples atribuições passando um objeto para o evento.

-

Cada chave do objeto será atribuída à instância.

-
import Nullstack from "nullstack";
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render() {
-    return (
-      <button onclick={{ count: this.count + 1 }}>
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-

Fonte de Evento

Por padrão, os eventos referem-se a this quando você passa um objeto.

-

Você pode usar o atributo source para definir qual objeto receberá as atribuições.

-
import Nullstack from "nullstack";
-
-class Paginator extends Nullstack {
-
-  render({ params }) {
-    return (
-      <button source={params} onclick={{ page: 1 }}>
-        Primeira Página
-      </button>
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

✨ Aprenda mais sobre a chave params do contexto.

-
-
-

💡 Se você não declarar uma fonte para o evento, o Nullstack injetará source={this} no tempo de transpilação para pular completamente o processo de pesquisa em tempo de execução!

-
-

Contexto de Evento

Os atributos do elemento-alvo do evento serão mesclados ao context da instância e podem ser desestruturados na assinatura da função.

-
import Nullstack from "nullstack";
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment({ delta }) {
-    this.count += delta;
-  }
-
-  render() {
-    return (
-      <button onclick={this.increment} delta={2}>
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 Qualquer atributo com valor primitivo será adicionado ao DOM.

-
-
-

✨ Considere usar atributos data para tornar seu HTML válido.

-
-

Evento Original

O comportamento padrão do navegador é impedido por padrão.

-

Você pode desativar isso declarando um atributo default para o elemento de evento.

-

Uma referência ao evento original é sempre mesclada com o contexto da função.

-
import Nullstack from "nullstack";
-
-class Form extends Nullstack {
-  submit({ event }) {
-    event.preventDefault();
-  }
-
-  render() {
-    return (
-      <form onsubmit={this.submit} default>
-        <button> Enviar </button>
-      </form>
-    )
-  }
-}
-
-export default Form;
-
-

Próximos passos

⚔ Aprenda sobre o ciclo da vida full-stack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/componentes-com-estado/index.html b/docs/pt-br/componentes-com-estado/index.html deleted file mode 100644 index e4eada75..00000000 --- a/docs/pt-br/componentes-com-estado/index.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - Componentes com estado - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes com estado

Um framework web full-stack produtivo não deve forçar você a pensar sobre detalhes de estrutura.

-

Nullstack assume o controle de suas subclasses e gera um proxy para cada instância.

-

Quando você invoca qualquer coisa em sua classe, você está na verdade dizendo ao Nullstack o que fazer com o ambiente nos bastidores.

-

Isso permite que você use operações de javascript vanilla como atribuir a uma variável e ver o reflexo no dom.

-

Mutabilidade

Você pode modificar variáveis ​​de instância para atualizar o estado do seu aplicativo.

-

As funções são vinculadas automaticamente ao proxy da instância e podem ser passadas como referência para eventos.

-

Os eventos são declarados como atributos HTML normais.

-
import Nullstack from "nullstack";
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment() {
-    this.count++;
-  }
-
-  render() {
-    return (
-      <button onclick={this.increment}>
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 As atualizações são feitas em lotes, geralmente enquanto aguardam chamadas assíncronas, portanto, fazer várias atribuições não tem custos de desempenho!

-
-

Objeto de Eventos

Você pode criar atalho em eventos que são simples atribuições passando um objeto para o evento.

-

Cada chave do objeto será atribuída à instância.

-
import Nullstack from "nullstack";
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render() {
-    return (
-      <button onclick={{ count: this.count + 1 }}>
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-

Fonte de Evento

Por padrão, os eventos referem-se a this quando você passa um objeto.

-

Você pode usar o atributo source para definir qual objeto receberá as atribuições.

-
import Nullstack from "nullstack";
-
-class Paginator extends Nullstack {
-
-  render({ params }) {
-    return (
-      <button source={params} onclick={{ page: 1 }}>
-        Primeira Página
-      </button>
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

✨ Aprenda mais sobre a chave params do contexto.

-
-
-

💡 Se você não declarar uma fonte para o evento, o Nullstack injetará source={this} no tempo de transpilação para pular completamente o processo de pesquisa em tempo de execução!

-
-

Contexto de Evento

Os atributos do elemento-alvo do evento serão mesclados ao context da instância e podem ser desestruturados na assinatura da função.

-
import Nullstack from "nullstack";
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment({ delta }) {
-    this.count += delta;
-  }
-
-  render() {
-    return (
-      <button onclick={this.increment} delta={2}>
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 Qualquer atributo com valor primitivo será adicionado ao DOM.

-
-
-

✨ Considere usar atributos data para tornar seu HTML válido.

-
-

Evento Original

O comportamento padrão do navegador é impedido por padrão.

-

Você pode desativar isso declarando um atributo default para o elemento de evento.

-

Uma referência ao evento original é sempre mesclada com o contexto da função.

-
import Nullstack from "nullstack";
-
-class Form extends Nullstack {
-  submit({ event }) {
-    event.preventDefault();
-  }
-
-  render() {
-    return (
-      <form onsubmit={this.submit} default>
-        <button> Enviar </button>
-      </form>
-    )
-  }
-}
-
-export default Form;
-
-

Próximos passos

⚔ Aprenda sobre o ciclo da vida full-stack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/componentes-com-estado/index.json b/docs/pt-br/componentes-com-estado/index.json deleted file mode 100644 index d2f64640..00000000 --- a/docs/pt-br/componentes-com-estado/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Componentes com estado","html":"

Um framework web full-stack produtivo não deve forçar você a pensar sobre detalhes de estrutura.

\n

Nullstack assume o controle de suas subclasses e gera um proxy para cada instância.

\n

Quando você invoca qualquer coisa em sua classe, você está na verdade dizendo ao Nullstack o que fazer com o ambiente nos bastidores.

\n

Isso permite que você use operações de javascript vanilla como atribuir a uma variável e ver o reflexo no dom.

\n

Mutabilidade

Você pode modificar variáveis ​​de instância para atualizar o estado do seu aplicativo.

\n

As funções são vinculadas automaticamente ao proxy da instância e podem ser passadas como referência para eventos.

\n

Os eventos são declarados como atributos HTML normais.

\n
import Nullstack from \"nullstack\";\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  increment() {\n    this.count++;\n  }\n\n  render() {\n    return (\n      <button onclick={this.increment}>\n        {this.count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
\n

💡 As atualizações são feitas em lotes, geralmente enquanto aguardam chamadas assíncronas, portanto, fazer várias atribuições não tem custos de desempenho!

\n
\n

Objeto de Eventos

Você pode criar atalho em eventos que são simples atribuições passando um objeto para o evento.

\n

Cada chave do objeto será atribuída à instância.

\n
import Nullstack from \"nullstack\";\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  render() {\n    return (\n      <button onclick={{ count: this.count + 1 }}>\n        {this.count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n

Fonte de Evento

Por padrão, os eventos referem-se a this quando você passa um objeto.

\n

Você pode usar o atributo source para definir qual objeto receberá as atribuições.

\n
import Nullstack from \"nullstack\";\n\nclass Paginator extends Nullstack {\n\n  render({ params }) {\n    return (\n      <button source={params} onclick={{ page: 1 }}>\n        Primeira Página\n      </button>\n    )\n  }\n\n}\n\nexport default Paginator;\n
\n
\n

✨ Aprenda mais sobre a chave params do contexto.

\n
\n
\n

💡 Se você não declarar uma fonte para o evento, o Nullstack injetará source={this} no tempo de transpilação para pular completamente o processo de pesquisa em tempo de execução!

\n
\n

Contexto de Evento

Os atributos do elemento-alvo do evento serão mesclados ao context da instância e podem ser desestruturados na assinatura da função.

\n
import Nullstack from \"nullstack\";\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  increment({ delta }) {\n    this.count += delta;\n  }\n\n  render() {\n    return (\n      <button onclick={this.increment} delta={2}>\n        {this.count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
\n

💡 Qualquer atributo com valor primitivo será adicionado ao DOM.

\n
\n
\n

✨ Considere usar atributos data para tornar seu HTML válido.

\n
\n

Evento Original

O comportamento padrão do navegador é impedido por padrão.

\n

Você pode desativar isso declarando um atributo default para o elemento de evento.

\n

Uma referência ao evento original é sempre mesclada com o contexto da função.

\n
import Nullstack from \"nullstack\";\n\nclass Form extends Nullstack {\n  submit({ event }) {\n    event.preventDefault();\n  }\n\n  render() {\n    return (\n      <form onsubmit={this.submit} default>\n        <button> Enviar </button>\n      </form>\n    )\n  }\n}\n\nexport default Form;\n
\n

Próximos passos

⚔ Aprenda sobre o ciclo da vida full-stack.

\n","description":"Um framework web full-stack produtivo não deve forçar você a pensar sobre detalhes de estrutura"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Componentes com estado - Nullstack","description":"Um framework web full-stack produtivo não deve forçar você a pensar sobre detalhes de estrutura"}} \ No newline at end of file diff --git a/docs/pt-br/componentes-renderizaveis.html b/docs/pt-br/componentes-renderizaveis.html deleted file mode 100644 index bee68210..00000000 --- a/docs/pt-br/componentes-renderizaveis.html +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - Componentes renderizáveis - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes renderizáveis

O componente mais simples que você pode fazer é um componente renderizável.

-

Componentes renderizáveis são muito semelhantes aos componentes da Web que fornecem a capacidade de criar novas tags HTML que atalham um grupo de outras tags HTML.

-

Crie um arquivo em sua pasta src com o nome de seu componente e com a extensão .njs.

-

Neste exemplo, vai ser chamado helloworld.njs.

-

Tudo o que você precisa fazer é importar nullstack ou qualquer uma das suas subclasses e estender sua classe dele, definir um método de instância chamado render que retorna qualquer JSX e exporte o componente.

-
-

✨ Instale a extensão oficial Nullstack para VSCode para gerar classes com snippets.

-
-
import Nullstack from "nullstack";
-
-class HelloWorld extends Nullstack {
-
-  render() {
-    return (
-      <div> Olá Mundo </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-

O código acima apenas declara o componente, você ainda tem que usá-lo.

-

Importando o componente em seu aplicativo, temos a capacidade de usar uma nova tag em sua renderização.

-

Esta tag será substituída pelo que você retornou no método render do componente.

-
import Nullstack from "nullstack";
-
-import "./Application.scss";
-
-import HelloWorld from "./HelloWorld";
-
-class Application extends Nullstack {
-  // ...
-
-  render({ page }) {
-    return (
-      <main>
-        <h1> {page.title} </h1>
-        <a href="https://nullstack.app/documentation" target="_blank">
-          Read the documentation
-        </a>
-        <HelloWorld />
-      </main>
-    )
-  }
-}
-
-export default Application;
-
-

Usando atributos HTML.

Nullstack JSX se desvia um pouco das especificações.

-

Você pode usar os atributos HTML normais como class e for diretamente.

-
<label for="input" class="nao-me-rotule"> Eu sou um rótulo </label>
-
-

Componentes Headless

Se você deseja pular a renderização do componente, você pode simplesmente retornar false da renderização.

-
import Nullstack from "nullstack";
-
-class Headless extends Nullstack {
-
-  render() {
-    return false;
-  }
-
-}
-
-export default Headless;
-
-

Isso alocará o espaço no DOM para quando você decidir renderizar a marcação lá.

-

Isso também é útil para renderização condicional.

-

Se tudo o que você deseja fazer é gerar um componente invisível, você pode ignorar a definição do método de renderização.

-

Componentes internos

Em vez de criar um novo componente apenas para organizar a divisão de código, você pode criar um componente interno.

-

Componentes internos são quaisquer métodos cujo nome seja iniciado com render seguido por um caractere maiúsculo.

-

Componentes internos compartilham a mesma instância e escopo, pois o componente principal, portanto, são muito convenientes para evitar problemas como adereços de perfuração.

-

Para invocar o componente interno, use uma tag JSX com o nome do método sem o prefixo render.

-
import Nullstack from "nullstack"
-
-class Post extends Nullstack {
-
-  renderArticle() {
-    return (
-      <article> Conteúdo </article>
-    )
-  }
-
-  renderAside() {
-    return (
-      <aside> Conteúdo Relacionado </aside>
-    )
-  }
-
-  render() {
-    return (
-      <div>
-        <Article />
-        <Aside />
-      </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-
-

💡 Nullstack injetará uma referência constante à função no tempo de transpilação, a fim de ignorar completamente o processo de pesquisa de tempo de execução!

-
-

Atributos booleanos

Os atributos podem ser atribuídos como booleanos.

-

Quando o valor é false, o atributo não será renderizado.

-

Quando o valor for true, ele será processado como um atributo booleano sem um valor de string.

-
<button disabled={false}> Botão </button>
-
-

Você pode abreviar atributos quando sabe que o valor será sempre verdadeiro.

-
<button disabled> Botão </button>
-
-
-

✨ Aprender mais sobre atributos.

-
-

Tag do elemento

Se você precisar decidir o nome da tag em tempo de execução, pode usar a tag do elemento e definir o atributo da tag condicionalmente.

-
<element tag={!!link ? "a" : "span"} href={link || false}>
-  algum texto arbitrário
-</element>
-
-

Quando o atributo tag é omitido, Nullstack assumirá como padrão um div.

-

Elementos SVG

O SVG pode ser usado como se fosse qualquer tag HTML normal.

-

Você pode manipular o SVG usando atributos e eventos normalmente.

-
<svg height={this.size} viewBox="0 0 100 100">
-  <circle cx="50" cy="50" r="40" onclick={this.grow} />
-</svg>
-
-
-

✨ Aprender mais sobre eventos.

-
-

Componentes com filhos

Seu componente pode ser invocado passando um bloco de conteúdo.

-
<Header>
-  <h1> Olá Mundo</h1>
-</Header>
-
-

Isso não renderiza automaticamente o bloco, pois não saberia onde colocá-lo.

-

Você pode desestruturar os filhos no método de renderização e colocá-los em sua marcação.

-
import Nullstack from "nullstack";
-
-class Header extends Nullstack {
-
-  render({ children }) {
-    return (
-      <div>{children}</div>
-    )
-  }
-
-}
-
-export default Header;
-
-
-

✨ Isso é possível porque a chave children faz parte do contexto da instância.

-
-

Listas

Você pode mapear listas sem declarar uma key.

-

As listas que podem mudar de comprimento devem ser agrupadas em um elemento pai apenas para elas.

-
<ul>
-  {list.map((item) => (
-    <li>{item.name}</li>
-  ))}
-</ul>
-
-

Você pode emular uma lista de tamanho fixo, retornando false em vez de um elemento para reservar espaço no Dom.

-
{list.map((item) => (
-  item.visible ? <div>{item.name}</div> : false
-)}
-
-

É uma boa prática usar componentes internos combinados com listas para limpar seu código.

-
import Nullstack from "nullstack";
-
-class List extends Nullstack {
-  items = [
-    { visible: true, number: 1 },
-    { visible: false, number: 2 },
-    { visible: true, number: 3 },
-  ]
-
-  renderItem({ visible, number }) {
-    if (!visible) return false;
-    return <li> {number} </li>
-  }
-
-  render() {
-    return (
-      <ul>
-        {this.items.map((item) => (
-          <Item {...item} />
-        ))}
-      </ul>
-    )
-  }
-}
-
-export default List;
-
-
-

✨ Às vezes, você notará chaves no mapa. Saiba mais sobre a key da instância.

-
-

HTML interno

Você pode definir o HTML interno de um elemento com o atributo html.

-

Links dentro da string HTML serão substituídos por Âncoras Roteáveis.

-
import Nullstack from "nullstack";
-
-class Post extends Nullstack {
-
-  content = `
-    <h1> Este é um post </h1>
-    <a href="/other-post">
-      Confira este outro post
-    </a>
-  `;
-
-  render() {
-    return (
-      <article html={this.content} />
-    )
-  }
-
-}
-
-export default Post;
-
-
-

🔥 Tome cuidado! Ao usar o HTML gerado pelo usuário, você está em risco de injeção de script

-
-

A tag head

Componentes renderizáveis podem renderizar dentro da tag head um número ilimitado de vezes em qualquer profundidade do aplicativo.

-

A tag head só será atualizada durante o processo de renderização no servidor e mudanças serão ignorados após o processo de hidratação.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <div>
-          <head>
-            <link rel="preconnect" href="https://www.googletagmanager.com" />
-          </head>
-        </div>
-        <head>
-          <link rel="preload" href="/roboto-v20-latin-300.woff2" as="font" type="font/woff2" crossorigin />
-          <link rel="preload" href="/crete-round-v9-latin-regular.woff2" as="font" type="font/woff2" crossorigin />
-        </head>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 Você não deve usar a tag head para atualizar metatags que o Nullstack já controla.

-
-

Próxima Etapa

⚔ Adicione estado ao seu componente usando componentes com estado.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/componentes-renderizaveis/index.html b/docs/pt-br/componentes-renderizaveis/index.html deleted file mode 100644 index bee68210..00000000 --- a/docs/pt-br/componentes-renderizaveis/index.html +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - Componentes renderizáveis - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes renderizáveis

O componente mais simples que você pode fazer é um componente renderizável.

-

Componentes renderizáveis são muito semelhantes aos componentes da Web que fornecem a capacidade de criar novas tags HTML que atalham um grupo de outras tags HTML.

-

Crie um arquivo em sua pasta src com o nome de seu componente e com a extensão .njs.

-

Neste exemplo, vai ser chamado helloworld.njs.

-

Tudo o que você precisa fazer é importar nullstack ou qualquer uma das suas subclasses e estender sua classe dele, definir um método de instância chamado render que retorna qualquer JSX e exporte o componente.

-
-

✨ Instale a extensão oficial Nullstack para VSCode para gerar classes com snippets.

-
-
import Nullstack from "nullstack";
-
-class HelloWorld extends Nullstack {
-
-  render() {
-    return (
-      <div> Olá Mundo </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-

O código acima apenas declara o componente, você ainda tem que usá-lo.

-

Importando o componente em seu aplicativo, temos a capacidade de usar uma nova tag em sua renderização.

-

Esta tag será substituída pelo que você retornou no método render do componente.

-
import Nullstack from "nullstack";
-
-import "./Application.scss";
-
-import HelloWorld from "./HelloWorld";
-
-class Application extends Nullstack {
-  // ...
-
-  render({ page }) {
-    return (
-      <main>
-        <h1> {page.title} </h1>
-        <a href="https://nullstack.app/documentation" target="_blank">
-          Read the documentation
-        </a>
-        <HelloWorld />
-      </main>
-    )
-  }
-}
-
-export default Application;
-
-

Usando atributos HTML.

Nullstack JSX se desvia um pouco das especificações.

-

Você pode usar os atributos HTML normais como class e for diretamente.

-
<label for="input" class="nao-me-rotule"> Eu sou um rótulo </label>
-
-

Componentes Headless

Se você deseja pular a renderização do componente, você pode simplesmente retornar false da renderização.

-
import Nullstack from "nullstack";
-
-class Headless extends Nullstack {
-
-  render() {
-    return false;
-  }
-
-}
-
-export default Headless;
-
-

Isso alocará o espaço no DOM para quando você decidir renderizar a marcação lá.

-

Isso também é útil para renderização condicional.

-

Se tudo o que você deseja fazer é gerar um componente invisível, você pode ignorar a definição do método de renderização.

-

Componentes internos

Em vez de criar um novo componente apenas para organizar a divisão de código, você pode criar um componente interno.

-

Componentes internos são quaisquer métodos cujo nome seja iniciado com render seguido por um caractere maiúsculo.

-

Componentes internos compartilham a mesma instância e escopo, pois o componente principal, portanto, são muito convenientes para evitar problemas como adereços de perfuração.

-

Para invocar o componente interno, use uma tag JSX com o nome do método sem o prefixo render.

-
import Nullstack from "nullstack"
-
-class Post extends Nullstack {
-
-  renderArticle() {
-    return (
-      <article> Conteúdo </article>
-    )
-  }
-
-  renderAside() {
-    return (
-      <aside> Conteúdo Relacionado </aside>
-    )
-  }
-
-  render() {
-    return (
-      <div>
-        <Article />
-        <Aside />
-      </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-
-

💡 Nullstack injetará uma referência constante à função no tempo de transpilação, a fim de ignorar completamente o processo de pesquisa de tempo de execução!

-
-

Atributos booleanos

Os atributos podem ser atribuídos como booleanos.

-

Quando o valor é false, o atributo não será renderizado.

-

Quando o valor for true, ele será processado como um atributo booleano sem um valor de string.

-
<button disabled={false}> Botão </button>
-
-

Você pode abreviar atributos quando sabe que o valor será sempre verdadeiro.

-
<button disabled> Botão </button>
-
-
-

✨ Aprender mais sobre atributos.

-
-

Tag do elemento

Se você precisar decidir o nome da tag em tempo de execução, pode usar a tag do elemento e definir o atributo da tag condicionalmente.

-
<element tag={!!link ? "a" : "span"} href={link || false}>
-  algum texto arbitrário
-</element>
-
-

Quando o atributo tag é omitido, Nullstack assumirá como padrão um div.

-

Elementos SVG

O SVG pode ser usado como se fosse qualquer tag HTML normal.

-

Você pode manipular o SVG usando atributos e eventos normalmente.

-
<svg height={this.size} viewBox="0 0 100 100">
-  <circle cx="50" cy="50" r="40" onclick={this.grow} />
-</svg>
-
-
-

✨ Aprender mais sobre eventos.

-
-

Componentes com filhos

Seu componente pode ser invocado passando um bloco de conteúdo.

-
<Header>
-  <h1> Olá Mundo</h1>
-</Header>
-
-

Isso não renderiza automaticamente o bloco, pois não saberia onde colocá-lo.

-

Você pode desestruturar os filhos no método de renderização e colocá-los em sua marcação.

-
import Nullstack from "nullstack";
-
-class Header extends Nullstack {
-
-  render({ children }) {
-    return (
-      <div>{children}</div>
-    )
-  }
-
-}
-
-export default Header;
-
-
-

✨ Isso é possível porque a chave children faz parte do contexto da instância.

-
-

Listas

Você pode mapear listas sem declarar uma key.

-

As listas que podem mudar de comprimento devem ser agrupadas em um elemento pai apenas para elas.

-
<ul>
-  {list.map((item) => (
-    <li>{item.name}</li>
-  ))}
-</ul>
-
-

Você pode emular uma lista de tamanho fixo, retornando false em vez de um elemento para reservar espaço no Dom.

-
{list.map((item) => (
-  item.visible ? <div>{item.name}</div> : false
-)}
-
-

É uma boa prática usar componentes internos combinados com listas para limpar seu código.

-
import Nullstack from "nullstack";
-
-class List extends Nullstack {
-  items = [
-    { visible: true, number: 1 },
-    { visible: false, number: 2 },
-    { visible: true, number: 3 },
-  ]
-
-  renderItem({ visible, number }) {
-    if (!visible) return false;
-    return <li> {number} </li>
-  }
-
-  render() {
-    return (
-      <ul>
-        {this.items.map((item) => (
-          <Item {...item} />
-        ))}
-      </ul>
-    )
-  }
-}
-
-export default List;
-
-
-

✨ Às vezes, você notará chaves no mapa. Saiba mais sobre a key da instância.

-
-

HTML interno

Você pode definir o HTML interno de um elemento com o atributo html.

-

Links dentro da string HTML serão substituídos por Âncoras Roteáveis.

-
import Nullstack from "nullstack";
-
-class Post extends Nullstack {
-
-  content = `
-    <h1> Este é um post </h1>
-    <a href="/other-post">
-      Confira este outro post
-    </a>
-  `;
-
-  render() {
-    return (
-      <article html={this.content} />
-    )
-  }
-
-}
-
-export default Post;
-
-
-

🔥 Tome cuidado! Ao usar o HTML gerado pelo usuário, você está em risco de injeção de script

-
-

A tag head

Componentes renderizáveis podem renderizar dentro da tag head um número ilimitado de vezes em qualquer profundidade do aplicativo.

-

A tag head só será atualizada durante o processo de renderização no servidor e mudanças serão ignorados após o processo de hidratação.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <div>
-          <head>
-            <link rel="preconnect" href="https://www.googletagmanager.com" />
-          </head>
-        </div>
-        <head>
-          <link rel="preload" href="/roboto-v20-latin-300.woff2" as="font" type="font/woff2" crossorigin />
-          <link rel="preload" href="/crete-round-v9-latin-regular.woff2" as="font" type="font/woff2" crossorigin />
-        </head>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 Você não deve usar a tag head para atualizar metatags que o Nullstack já controla.

-
-

Próxima Etapa

⚔ Adicione estado ao seu componente usando componentes com estado.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/componentes-renderizaveis/index.json b/docs/pt-br/componentes-renderizaveis/index.json deleted file mode 100644 index 0b6db1ca..00000000 --- a/docs/pt-br/componentes-renderizaveis/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Componentes renderizáveis","html":"

O componente mais simples que você pode fazer é um componente renderizável.

\n

Componentes renderizáveis são muito semelhantes aos componentes da Web que fornecem a capacidade de criar novas tags HTML que atalham um grupo de outras tags HTML.

\n

Crie um arquivo em sua pasta src com o nome de seu componente e com a extensão .njs.

\n

Neste exemplo, vai ser chamado helloworld.njs.

\n

Tudo o que você precisa fazer é importar nullstack ou qualquer uma das suas subclasses e estender sua classe dele, definir um método de instância chamado render que retorna qualquer JSX e exporte o componente.

\n
\n

✨ Instale a extensão oficial Nullstack para VSCode para gerar classes com snippets.

\n
\n
import Nullstack from \"nullstack\";\n\nclass HelloWorld extends Nullstack {\n\n  render() {\n    return (\n      <div> Olá Mundo </div>\n    )\n  }\n\n}\n\nexport default HelloWorld;\n
\n

O código acima apenas declara o componente, você ainda tem que usá-lo.

\n

Importando o componente em seu aplicativo, temos a capacidade de usar uma nova tag em sua renderização.

\n

Esta tag será substituída pelo que você retornou no método render do componente.

\n
import Nullstack from \"nullstack\";\n\nimport \"./Application.scss\";\n\nimport HelloWorld from \"./HelloWorld\";\n\nclass Application extends Nullstack {\n  // ...\n\n  render({ page }) {\n    return (\n      <main>\n        <h1> {page.title} </h1>\n        <a href=\"https://nullstack.app/documentation\" target=\"_blank\">\n          Read the documentation\n        </a>\n        <HelloWorld />\n      </main>\n    )\n  }\n}\n\nexport default Application;\n
\n

Usando atributos HTML.

Nullstack JSX se desvia um pouco das especificações.

\n

Você pode usar os atributos HTML normais como class e for diretamente.

\n
<label for=\"input\" class=\"nao-me-rotule\"> Eu sou um rótulo </label>\n
\n

Componentes Headless

Se você deseja pular a renderização do componente, você pode simplesmente retornar false da renderização.

\n
import Nullstack from \"nullstack\";\n\nclass Headless extends Nullstack {\n\n  render() {\n    return false;\n  }\n\n}\n\nexport default Headless;\n
\n

Isso alocará o espaço no DOM para quando você decidir renderizar a marcação lá.

\n

Isso também é útil para renderização condicional.

\n

Se tudo o que você deseja fazer é gerar um componente invisível, você pode ignorar a definição do método de renderização.

\n

Componentes internos

Em vez de criar um novo componente apenas para organizar a divisão de código, você pode criar um componente interno.

\n

Componentes internos são quaisquer métodos cujo nome seja iniciado com render seguido por um caractere maiúsculo.

\n

Componentes internos compartilham a mesma instância e escopo, pois o componente principal, portanto, são muito convenientes para evitar problemas como adereços de perfuração.

\n

Para invocar o componente interno, use uma tag JSX com o nome do método sem o prefixo render.

\n
import Nullstack from \"nullstack\"\n\nclass Post extends Nullstack {\n\n  renderArticle() {\n    return (\n      <article> Conteúdo </article>\n    )\n  }\n\n  renderAside() {\n    return (\n      <aside> Conteúdo Relacionado </aside>\n    )\n  }\n\n  render() {\n    return (\n      <div>\n        <Article />\n        <Aside />\n      </div>\n    )\n  }\n\n}\n\nexport default HelloWorld;\n
\n
\n

💡 Nullstack injetará uma referência constante à função no tempo de transpilação, a fim de ignorar completamente o processo de pesquisa de tempo de execução!

\n
\n

Atributos booleanos

Os atributos podem ser atribuídos como booleanos.

\n

Quando o valor é false, o atributo não será renderizado.

\n

Quando o valor for true, ele será processado como um atributo booleano sem um valor de string.

\n
<button disabled={false}> Botão </button>\n
\n

Você pode abreviar atributos quando sabe que o valor será sempre verdadeiro.

\n
<button disabled> Botão </button>\n
\n
\n

✨ Aprender mais sobre atributos.

\n
\n

Tag do elemento

Se você precisar decidir o nome da tag em tempo de execução, pode usar a tag do elemento e definir o atributo da tag condicionalmente.

\n
<element tag={!!link ? \"a\" : \"span\"} href={link || false}>\n  algum texto arbitrário\n</element>\n
\n

Quando o atributo tag é omitido, Nullstack assumirá como padrão um div.

\n

Elementos SVG

O SVG pode ser usado como se fosse qualquer tag HTML normal.

\n

Você pode manipular o SVG usando atributos e eventos normalmente.

\n
<svg height={this.size} viewBox=\"0 0 100 100\">\n  <circle cx=\"50\" cy=\"50\" r=\"40\" onclick={this.grow} />\n</svg>\n
\n
\n

✨ Aprender mais sobre eventos.

\n
\n

Componentes com filhos

Seu componente pode ser invocado passando um bloco de conteúdo.

\n
<Header>\n  <h1> Olá Mundo</h1>\n</Header>\n
\n

Isso não renderiza automaticamente o bloco, pois não saberia onde colocá-lo.

\n

Você pode desestruturar os filhos no método de renderização e colocá-los em sua marcação.

\n
import Nullstack from \"nullstack\";\n\nclass Header extends Nullstack {\n\n  render({ children }) {\n    return (\n      <div>{children}</div>\n    )\n  }\n\n}\n\nexport default Header;\n
\n
\n

✨ Isso é possível porque a chave children faz parte do contexto da instância.

\n
\n

Listas

Você pode mapear listas sem declarar uma key.

\n

As listas que podem mudar de comprimento devem ser agrupadas em um elemento pai apenas para elas.

\n
<ul>\n  {list.map((item) => (\n    <li>{item.name}</li>\n  ))}\n</ul>\n
\n

Você pode emular uma lista de tamanho fixo, retornando false em vez de um elemento para reservar espaço no Dom.

\n
{list.map((item) => (\n  item.visible ? <div>{item.name}</div> : false\n)}\n
\n

É uma boa prática usar componentes internos combinados com listas para limpar seu código.

\n
import Nullstack from \"nullstack\";\n\nclass List extends Nullstack {\n  items = [\n    { visible: true, number: 1 },\n    { visible: false, number: 2 },\n    { visible: true, number: 3 },\n  ]\n\n  renderItem({ visible, number }) {\n    if (!visible) return false;\n    return <li> {number} </li>\n  }\n\n  render() {\n    return (\n      <ul>\n        {this.items.map((item) => (\n          <Item {...item} />\n        ))}\n      </ul>\n    )\n  }\n}\n\nexport default List;\n
\n
\n

✨ Às vezes, você notará chaves no mapa. Saiba mais sobre a key da instância.

\n
\n

HTML interno

Você pode definir o HTML interno de um elemento com o atributo html.

\n

Links dentro da string HTML serão substituídos por Âncoras Roteáveis.

\n
import Nullstack from \"nullstack\";\n\nclass Post extends Nullstack {\n\n  content = `\n    <h1> Este é um post </h1>\n    <a href=\"/other-post\">\n      Confira este outro post\n    </a>\n  `;\n\n  render() {\n    return (\n      <article html={this.content} />\n    )\n  }\n\n}\n\nexport default Post;\n
\n
\n

🔥 Tome cuidado! Ao usar o HTML gerado pelo usuário, você está em risco de injeção de script

\n
\n

A tag head

Componentes renderizáveis podem renderizar dentro da tag head um número ilimitado de vezes em qualquer profundidade do aplicativo.

\n

A tag head só será atualizada durante o processo de renderização no servidor e mudanças serão ignorados após o processo de hidratação.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <div>\n          <head>\n            <link rel=\"preconnect\" href=\"https://www.googletagmanager.com\" />\n          </head>\n        </div>\n        <head>\n          <link rel=\"preload\" href=\"/roboto-v20-latin-300.woff2\" as=\"font\" type=\"font/woff2\" crossorigin />\n          <link rel=\"preload\" href=\"/crete-round-v9-latin-regular.woff2\" as=\"font\" type=\"font/woff2\" crossorigin />\n        </head>\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n
\n

🔥 Você não deve usar a tag head para atualizar metatags que o Nullstack já controla.

\n
\n

Próxima Etapa

⚔ Adicione estado ao seu componente usando componentes com estado.

\n","description":"Componentes renderizáveis são muito semelhantes aos componentes da Web que fornecem a capacidade de criar novas tags HTML que atalham um grupo de outras tags HTML"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Componentes renderizáveis - Nullstack","description":"Componentes renderizáveis são muito semelhantes aos componentes da Web que fornecem a capacidade de criar novas tags HTML que atalham um grupo de outras tags HTML"}} \ No newline at end of file diff --git a/docs/pt-br/componentes.html b/docs/pt-br/componentes.html deleted file mode 100644 index df0feba6..00000000 --- a/docs/pt-br/componentes.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Componentes da Comunidade - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes da Comunidade

Uma lista com curadoria de componentes Nullstack feitos pela comunidade.

Se você deseja adicionar um componente a esta lista, abra uma issue no github.

- - - \ No newline at end of file diff --git a/docs/pt-br/componentes/index.html b/docs/pt-br/componentes/index.html deleted file mode 100644 index df0feba6..00000000 --- a/docs/pt-br/componentes/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Componentes da Comunidade - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes da Comunidade

Uma lista com curadoria de componentes Nullstack feitos pela comunidade.

Se você deseja adicionar um componente a esta lista, abra uma issue no github.

- - - \ No newline at end of file diff --git a/docs/pt-br/componentes/index.json b/docs/pt-br/componentes/index.json deleted file mode 100644 index 0dd86fd7..00000000 --- a/docs/pt-br/componentes/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-6":{"locale":"pt-BR","i18n":{"title":"Componentes da Comunidade","description":"Uma lista com curadoria de componentes Nullstack feitos pela comunidade.","heading":"Componentes da Comunidade","tagline":"Uma lista com curadoria de componentes Nullstack feitos pela comunidade.","contribute":"Se você deseja adicionar um componente a esta lista, abra uma issue no github.","topics":[{"title":"Integrações","projects":[{"title":"Google Analytics","repository":"https://github.com/Mortaro/nullstack-google-analytics"},{"title":"Facebook Pixel","repository":"https://github.com/Mortaro/nullstack-facebook-pixel"}]},{"title":"Inputs Gerais","projects":[{"title":"Input Monetário","repository":"https://github.com/Mortaro/nullstack-currency-input"},{"title":"Input de Data","repository":"https://github.com/Mortaro/nullstack-date-input"},{"title":"Adaptador para CKEditor","repository":"https://github.com/Mortaro/nullstack-ckeditor-adapter"},{"title":"Input para Upload de Arquivo","repository":"https://github.com/Mortaro/nullstack-upload-input"}]},{"title":"Inputs Brasileiros","tagline":{"title":"English: Nullstack is a Brazilian Framework","text":"🤘 Nullstack é BR porr@!"},"projects":[{"title":"Inputs para CPF e CNPJ","repository":"https://github.com/Mortaro/nullstack-cpf-cnpj-input"},{"title":"Input para CEP","repository":"https://github.com/Mortaro/nullstack-cep-input"},{"title":"Input para Telefone","repository":"https://github.com/Mortaro/nullstack-phone-input"}]}]}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"priority":0.3,"title":"Componentes da Comunidade - Nullstack","description":"Uma lista com curadoria de componentes Nullstack feitos pela comunidade.","locale":"pt-BR"}} \ No newline at end of file diff --git a/docs/pt-br/contexto-data.html b/docs/pt-br/contexto-data.html deleted file mode 100644 index 1033d54c..00000000 --- a/docs/pt-br/contexto-data.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - Contexto Data - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Data

    -
  • Tipo: object
  • -
  • Origem: Contexto Componente
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client
  • -
-

Ele te dá informações sobre o conjunto de dados do elemento.

-

Você pode usar esta chave para evitar poluir seu DOM com atributos inválidos.

-
-

💡 Isso ajuda o Nullstack a definir atributos sem perder tempo validando-os.

-
-

Quaisquer atributos data-* receberão uma chave camelizada respectiva no objeto data.

-

Você pode atribuir atributos data ambos via data-* e uma chave data que aceita um objeto com chaves camelizadas.

-

A versão kebab também está disponível no contexto.

-
import Nullstack from "nullstack"
-
-class ContextData extends Nullstack {
-  count = 1
-
-  calculate({ data }) {
-    this.count = this.count * data.multiply + data.sum
-  }
-
-  renderInner(context) {
-    const { data } = context
-    return (
-      <div data={data}>
-        {data.frameworkName}é o mesmo que
-        {context["data-framework-name"]}
-      </div>
-    )
-  }
-
-  render({ data }) {
-    return (
-      <div>
-        <button onclick={this.calculate} data-multiply={3} data={{ sum: 2 }}>
-          Calcular
-        </button>
-        <Inner data-framework-name="Nullstack" />
-      </div>
-    )
-  }
-}
-
-export default ContextData
-
-
-

💡 Chaves camelizadas do objeto data resultarão em atributos kebab no DOM.

-
-

Próxima Etapa

⚔ Aprenda sobre a chave environment do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-data/index.html b/docs/pt-br/contexto-data/index.html deleted file mode 100644 index 1033d54c..00000000 --- a/docs/pt-br/contexto-data/index.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - Contexto Data - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Data

    -
  • Tipo: object
  • -
  • Origem: Contexto Componente
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client
  • -
-

Ele te dá informações sobre o conjunto de dados do elemento.

-

Você pode usar esta chave para evitar poluir seu DOM com atributos inválidos.

-
-

💡 Isso ajuda o Nullstack a definir atributos sem perder tempo validando-os.

-
-

Quaisquer atributos data-* receberão uma chave camelizada respectiva no objeto data.

-

Você pode atribuir atributos data ambos via data-* e uma chave data que aceita um objeto com chaves camelizadas.

-

A versão kebab também está disponível no contexto.

-
import Nullstack from "nullstack"
-
-class ContextData extends Nullstack {
-  count = 1
-
-  calculate({ data }) {
-    this.count = this.count * data.multiply + data.sum
-  }
-
-  renderInner(context) {
-    const { data } = context
-    return (
-      <div data={data}>
-        {data.frameworkName}é o mesmo que
-        {context["data-framework-name"]}
-      </div>
-    )
-  }
-
-  render({ data }) {
-    return (
-      <div>
-        <button onclick={this.calculate} data-multiply={3} data={{ sum: 2 }}>
-          Calcular
-        </button>
-        <Inner data-framework-name="Nullstack" />
-      </div>
-    )
-  }
-}
-
-export default ContextData
-
-
-

💡 Chaves camelizadas do objeto data resultarão em atributos kebab no DOM.

-
-

Próxima Etapa

⚔ Aprenda sobre a chave environment do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-data/index.json b/docs/pt-br/contexto-data/index.json deleted file mode 100644 index 390bd67e..00000000 --- a/docs/pt-br/contexto-data/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Data","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Componente
  • \n
  • Disponibilidade: client
  • \n
  • readonly no contexto do client
  • \n
\n

Ele te dá informações sobre o conjunto de dados do elemento.

\n

Você pode usar esta chave para evitar poluir seu DOM com atributos inválidos.

\n
\n

💡 Isso ajuda o Nullstack a definir atributos sem perder tempo validando-os.

\n
\n

Quaisquer atributos data-* receberão uma chave camelizada respectiva no objeto data.

\n

Você pode atribuir atributos data ambos via data-* e uma chave data que aceita um objeto com chaves camelizadas.

\n

A versão kebab também está disponível no contexto.

\n
import Nullstack from \"nullstack\"\n\nclass ContextData extends Nullstack {\n  count = 1\n\n  calculate({ data }) {\n    this.count = this.count * data.multiply + data.sum\n  }\n\n  renderInner(context) {\n    const { data } = context\n    return (\n      <div data={data}>\n        {data.frameworkName}é o mesmo que\n        {context[\"data-framework-name\"]}\n      </div>\n    )\n  }\n\n  render({ data }) {\n    return (\n      <div>\n        <button onclick={this.calculate} data-multiply={3} data={{ sum: 2 }}>\n          Calcular\n        </button>\n        <Inner data-framework-name=\"Nullstack\" />\n      </div>\n    )\n  }\n}\n\nexport default ContextData\n
\n
\n

💡 Chaves camelizadas do objeto data resultarão em atributos kebab no DOM.

\n
\n

Próxima Etapa

⚔ Aprenda sobre a chave environment do contexto.

\n","description":"O objeto data é um proxy no Contexto Componente disponível no client e te dá informações sobre o conjunto de dados do elemento"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Data - Nullstack","description":"O objeto data é um proxy no Contexto Componente disponível no client e te dá informações sobre o conjunto de dados do elemento"}} \ No newline at end of file diff --git a/docs/pt-br/contexto-environment.html b/docs/pt-br/contexto-environment.html deleted file mode 100644 index 2715aac9..00000000 --- a/docs/pt-br/contexto-environment.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Contexto Environment - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Environment

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readonly em ambos server e client
  • -
-

Ele te dá informações sobre o ambiente atual.

-

As seguintes chaves estão disponíveis no objeto:

-
    -
  • client: boolean
  • -
  • server: boolean
  • -
  • development: boolean
  • -
  • production: boolean
  • -
  • static: boolean
  • -
  • key: string
  • -
-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
- 
-  render({environment}) {
-    return (
-      <div> 
-        {environment.client && <p>Estou no cliente</p>}
-        {environment.server && <p>Estou no servidor</p>}
-        {environment.development && <p>Estou em modo de desenvolvimento</p>}
-        {environment.production && <p>Estou em modo de produção</p>}
-        {environment.static && <p>Estou em um site estático</p>}
-        <p>Minha chave é {environment.key}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

A chave key do environment é um hash md5 das saídas da pasta do ambiente atual. A key é anexada nos caminhos dos assets e na API estática para auxiliar no controle de cache.

-

Próxima Etapa

⚔ Aprenda sobre a chave page do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-environment/index.html b/docs/pt-br/contexto-environment/index.html deleted file mode 100644 index 2715aac9..00000000 --- a/docs/pt-br/contexto-environment/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - Contexto Environment - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Environment

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readonly em ambos server e client
  • -
-

Ele te dá informações sobre o ambiente atual.

-

As seguintes chaves estão disponíveis no objeto:

-
    -
  • client: boolean
  • -
  • server: boolean
  • -
  • development: boolean
  • -
  • production: boolean
  • -
  • static: boolean
  • -
  • key: string
  • -
-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
- 
-  render({environment}) {
-    return (
-      <div> 
-        {environment.client && <p>Estou no cliente</p>}
-        {environment.server && <p>Estou no servidor</p>}
-        {environment.development && <p>Estou em modo de desenvolvimento</p>}
-        {environment.production && <p>Estou em modo de produção</p>}
-        {environment.static && <p>Estou em um site estático</p>}
-        <p>Minha chave é {environment.key}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

A chave key do environment é um hash md5 das saídas da pasta do ambiente atual. A key é anexada nos caminhos dos assets e na API estática para auxiliar no controle de cache.

-

Próxima Etapa

⚔ Aprenda sobre a chave page do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-environment/index.json b/docs/pt-br/contexto-environment/index.json deleted file mode 100644 index 5355a77f..00000000 --- a/docs/pt-br/contexto-environment/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Environment","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: server/client
  • \n
  • readonly em ambos server e client
  • \n
\n

Ele te dá informações sobre o ambiente atual.

\n

As seguintes chaves estão disponíveis no objeto:

\n
    \n
  • client: boolean
  • \n
  • server: boolean
  • \n
  • development: boolean
  • \n
  • production: boolean
  • \n
  • static: boolean
  • \n
  • key: string
  • \n
\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n \n  render({environment}) {\n    return (\n      <div> \n        {environment.client && <p>Estou no cliente</p>}\n        {environment.server && <p>Estou no servidor</p>}\n        {environment.development && <p>Estou em modo de desenvolvimento</p>}\n        {environment.production && <p>Estou em modo de produção</p>}\n        {environment.static && <p>Estou em um site estático</p>}\n        <p>Minha chave é {environment.key}</p>\n      </div>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

A chave key do environment é um hash md5 das saídas da pasta do ambiente atual. A key é anexada nos caminhos dos assets e na API estática para auxiliar no controle de cache.

\n

Próxima Etapa

⚔ Aprenda sobre a chave page do contexto.

\n","description":"O objeto environment é um proxy no Contexto Nullstack disponível em ambos client e server e te dá informações sobre o ambiente atual"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Environment - Nullstack","description":"O objeto environment é um proxy no Contexto Nullstack disponível em ambos client e server e te dá informações sobre o ambiente atual"}} \ No newline at end of file diff --git a/docs/pt-br/contexto-page.html b/docs/pt-br/contexto-page.html deleted file mode 100644 index 80beb65c..00000000 --- a/docs/pt-br/contexto-page.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - Contexto Page - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Page

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite em ambos server e client
  • -
-

Ele fornece informações sobre as metatags da head do documento.

-

Chaves de page serão usadas para gerar as metatags durante a renderização no lado do servidor e devem ser atribuídas antes do ciclo initiate ser resolvido.

-

As seguintes chaves estão disponíveis no objeto:

-
    -
  • title: string
  • -
  • image: string (URL absoluto ou relativo)
  • -
  • description: string
  • -
  • canonical: string (URL absoluto ou relativo)
  • -
  • locale: string
  • -
  • robots: string
  • -
  • schema: object
  • -
  • changes: string
  • -
  • priority: number
  • -
  • status: number
  • -
-

Quando a chave title é atribuída no lado do client, o título do documento será atualizado.

-

Nullstack utiliza as chaves changes e priority para gerar o sitemap.xml.

-

O mapa do site é gerado automaticamente apenas ao utilizar a geração de site estático e deve ser gerado manualmente em aplicativos com a renderização no lado do servidor.

-

A chave changes representa a chave changefreq no sitemap.xml e se for atribuída deverá ser um dos seguintes valores:

-
    -
  • always
  • -
  • hourly
  • -
  • daily
  • -
  • weekly
  • -
  • monthly
  • -
  • yearly
  • -
  • never
  • -
-

A chave priority é um número entre 0.0 e 1.0 que representa a chave priority no sitemap.xml.

-

Nullstack não define uma prioridade padrão, no entanto, sitemaps assumem uma prioridade 0.5 quando não são definidas explicitamente.

-

Além de title e locale, todas as outras chaves tem padrões sensíveis e gerados com base no escopo do aplicativo.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  prepare({project, page}) {
-    page.title = `${project.name} - Título da página`;
-    page.image = '/imagem.jpg';
-    page.description = 'Meta descrição da página';
-    page.canonical = 'http://absoluto.url/canonical-link';
-    page.locale = 'pt-BR';
-    page.robots = 'index, follow';
-    page.schema = {};
-    page.changes = 'weekly';
-    page.priority = 1;
-  }
-
-  render({page}) {
-    return (
-      <div>
-        <h1>{page.title}</h1>
-        <p>{page.description}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

Eventos Personalizados

Atualizando page.title gerará um evento personalizado.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({page}) {
-    window.addEventListener(page.event, () => {
-      console.log(page.title);
-    });
-  }
-
-}
-
-export default Analytics;
-
-

Páginas de erro

Se durante o processo de renderização no lado do servidor o page.status estiver com qualquer valor além de 200, seu aplicativo receberá outra passagem na renderização e lhe possibilitará ajustar a interface de acordo com o status retornado.

-

A chave status será gerada na resposta HTTP.

-

O status da página será modificado para 500 e receberá outra passagem na renderização se a página gerar uma exceção enquanto renderiza.

-

O status das respostas de funções do servidor será definido no page.status.

-
import Nullstack from 'nullstack';
-import ErrorPage from './ErrorPage';
-import HomePage from './HomePage';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render({page}) {
-    return (
-      <main>
-        {page.status !== 200 && <ErrorPage route="*" />}
-        <HomePage route="/" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 A atribuição à chave status durante o modo aplicativo de página única não terá efeito.

-
-

Próximo Passo

⚔ Aprenda sobre a chave project do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-page/index.html b/docs/pt-br/contexto-page/index.html deleted file mode 100644 index 80beb65c..00000000 --- a/docs/pt-br/contexto-page/index.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - Contexto Page - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Page

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite em ambos server e client
  • -
-

Ele fornece informações sobre as metatags da head do documento.

-

Chaves de page serão usadas para gerar as metatags durante a renderização no lado do servidor e devem ser atribuídas antes do ciclo initiate ser resolvido.

-

As seguintes chaves estão disponíveis no objeto:

-
    -
  • title: string
  • -
  • image: string (URL absoluto ou relativo)
  • -
  • description: string
  • -
  • canonical: string (URL absoluto ou relativo)
  • -
  • locale: string
  • -
  • robots: string
  • -
  • schema: object
  • -
  • changes: string
  • -
  • priority: number
  • -
  • status: number
  • -
-

Quando a chave title é atribuída no lado do client, o título do documento será atualizado.

-

Nullstack utiliza as chaves changes e priority para gerar o sitemap.xml.

-

O mapa do site é gerado automaticamente apenas ao utilizar a geração de site estático e deve ser gerado manualmente em aplicativos com a renderização no lado do servidor.

-

A chave changes representa a chave changefreq no sitemap.xml e se for atribuída deverá ser um dos seguintes valores:

-
    -
  • always
  • -
  • hourly
  • -
  • daily
  • -
  • weekly
  • -
  • monthly
  • -
  • yearly
  • -
  • never
  • -
-

A chave priority é um número entre 0.0 e 1.0 que representa a chave priority no sitemap.xml.

-

Nullstack não define uma prioridade padrão, no entanto, sitemaps assumem uma prioridade 0.5 quando não são definidas explicitamente.

-

Além de title e locale, todas as outras chaves tem padrões sensíveis e gerados com base no escopo do aplicativo.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  prepare({project, page}) {
-    page.title = `${project.name} - Título da página`;
-    page.image = '/imagem.jpg';
-    page.description = 'Meta descrição da página';
-    page.canonical = 'http://absoluto.url/canonical-link';
-    page.locale = 'pt-BR';
-    page.robots = 'index, follow';
-    page.schema = {};
-    page.changes = 'weekly';
-    page.priority = 1;
-  }
-
-  render({page}) {
-    return (
-      <div>
-        <h1>{page.title}</h1>
-        <p>{page.description}</p>
-      </div>
-    )
-  }
-
-}
-
-export default Page;
-
-

Eventos Personalizados

Atualizando page.title gerará um evento personalizado.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({page}) {
-    window.addEventListener(page.event, () => {
-      console.log(page.title);
-    });
-  }
-
-}
-
-export default Analytics;
-
-

Páginas de erro

Se durante o processo de renderização no lado do servidor o page.status estiver com qualquer valor além de 200, seu aplicativo receberá outra passagem na renderização e lhe possibilitará ajustar a interface de acordo com o status retornado.

-

A chave status será gerada na resposta HTTP.

-

O status da página será modificado para 500 e receberá outra passagem na renderização se a página gerar uma exceção enquanto renderiza.

-

O status das respostas de funções do servidor será definido no page.status.

-
import Nullstack from 'nullstack';
-import ErrorPage from './ErrorPage';
-import HomePage from './HomePage';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render({page}) {
-    return (
-      <main>
-        {page.status !== 200 && <ErrorPage route="*" />}
-        <HomePage route="/" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 A atribuição à chave status durante o modo aplicativo de página única não terá efeito.

-
-

Próximo Passo

⚔ Aprenda sobre a chave project do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-page/index.json b/docs/pt-br/contexto-page/index.json deleted file mode 100644 index 27532f3e..00000000 --- a/docs/pt-br/contexto-page/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Page","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: server/client
  • \n
  • readwrite em ambos server e client
  • \n
\n

Ele fornece informações sobre as metatags da head do documento.

\n

Chaves de page serão usadas para gerar as metatags durante a renderização no lado do servidor e devem ser atribuídas antes do ciclo initiate ser resolvido.

\n

As seguintes chaves estão disponíveis no objeto:

\n
    \n
  • title: string
  • \n
  • image: string (URL absoluto ou relativo)
  • \n
  • description: string
  • \n
  • canonical: string (URL absoluto ou relativo)
  • \n
  • locale: string
  • \n
  • robots: string
  • \n
  • schema: object
  • \n
  • changes: string
  • \n
  • priority: number
  • \n
  • status: number
  • \n
\n

Quando a chave title é atribuída no lado do client, o título do documento será atualizado.

\n

Nullstack utiliza as chaves changes e priority para gerar o sitemap.xml.

\n

O mapa do site é gerado automaticamente apenas ao utilizar a geração de site estático e deve ser gerado manualmente em aplicativos com a renderização no lado do servidor.

\n

A chave changes representa a chave changefreq no sitemap.xml e se for atribuída deverá ser um dos seguintes valores:

\n
    \n
  • always
  • \n
  • hourly
  • \n
  • daily
  • \n
  • weekly
  • \n
  • monthly
  • \n
  • yearly
  • \n
  • never
  • \n
\n

A chave priority é um número entre 0.0 e 1.0 que representa a chave priority no sitemap.xml.

\n

Nullstack não define uma prioridade padrão, no entanto, sitemaps assumem uma prioridade 0.5 quando não são definidas explicitamente.

\n

Além de title e locale, todas as outras chaves tem padrões sensíveis e gerados com base no escopo do aplicativo.

\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n\n  prepare({project, page}) {\n    page.title = `${project.name} - Título da página`;\n    page.image = '/imagem.jpg';\n    page.description = 'Meta descrição da página';\n    page.canonical = 'http://absoluto.url/canonical-link';\n    page.locale = 'pt-BR';\n    page.robots = 'index, follow';\n    page.schema = {};\n    page.changes = 'weekly';\n    page.priority = 1;\n  }\n\n  render({page}) {\n    return (\n      <div>\n        <h1>{page.title}</h1>\n        <p>{page.description}</p>\n      </div>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Eventos Personalizados

Atualizando page.title gerará um evento personalizado.

\n
import Nullstack from 'nullstack';\n\nclass Analytics extends Nullstack {\n\n  hydrate({page}) {\n    window.addEventListener(page.event, () => {\n      console.log(page.title);\n    });\n  }\n\n}\n\nexport default Analytics;\n
\n

Páginas de erro

Se durante o processo de renderização no lado do servidor o page.status estiver com qualquer valor além de 200, seu aplicativo receberá outra passagem na renderização e lhe possibilitará ajustar a interface de acordo com o status retornado.

\n

A chave status será gerada na resposta HTTP.

\n

O status da página será modificado para 500 e receberá outra passagem na renderização se a página gerar uma exceção enquanto renderiza.

\n

O status das respostas de funções do servidor será definido no page.status.

\n
import Nullstack from 'nullstack';\nimport ErrorPage from './ErrorPage';\nimport HomePage from './HomePage';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render({page}) {\n    return (\n      <main>\n        {page.status !== 200 && <ErrorPage route=\"*\" />}\n        <HomePage route=\"/\" />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n
\n

🔥 A atribuição à chave status durante o modo aplicativo de página única não terá efeito.

\n
\n

Próximo Passo

⚔ Aprenda sobre a chave project do contexto.

\n","description":"O objeto page é um proxy no Contexto Nullstack disponível em ambos client e server e te dá informações sobre as metatags da head do documento"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Page - Nullstack","description":"O objeto page é um proxy no Contexto Nullstack disponível em ambos client e server e te dá informações sobre as metatags da head do documento"}} \ No newline at end of file diff --git a/docs/pt-br/contexto-project.html b/docs/pt-br/contexto-project.html deleted file mode 100644 index 91b0f21f..00000000 --- a/docs/pt-br/contexto-project.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - Contexto Project - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Project

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite no contexto do server
  • -
  • readonly no contexto do client
  • -
-

Ele te dá informações sobre o manifest do app e algumas metatags.

-

As chaves de project serão usadas para gerar metatags durante a renderização do lado do servidor e devem ser definidas antes que initiate seja resolvido.

-

As chaves de project serão usadas para gerar o manifest do app e devem ser definidas durante a inicialização da aplicação.

-

A chave disallow será usada para gerar o robots.txt e deverá ser definida durante a inicialização da aplicação.

-

As chaves de project serão congeladas após a inicialização da aplicação.

-

As chaves a seguir estão disponíveis no objeto:

-
    -
  • domain: string
  • -
  • name: string
  • -
  • shortName: string
  • -
  • color: string
  • -
  • backgroundColor: string
  • -
  • type: string
  • -
  • display: string
  • -
  • orientation: string
  • -
  • scope: string
  • -
  • root: string
  • -
  • icons: object
  • -
  • favicon: string (url relativo ou absoluto)
  • -
  • disallow: array de string (caminhos relativos)
  • -
  • sitemap: boolean ou string (url relativo ou absoluto)
  • -
  • cdn: string (url absoluto)
  • -
  • protocol: string (http or https)
  • -
-

Além de domain, name and color todas as outras chaves tem padrões sensíveis gerados com base no escopo do aplicativo.

-

Se você não declarar a chave icons, Nullstack irá escanear quaisquer ícones com o nome seguindo o padrão "icon-[LARGURA]x[ALTURA].png" na sua pasta public.

-

Se a chave sitemap estiver definida como true o seu arquivo robots.txt irá apontar o sitemap para https://${project.domain}/sitemap.xml.

-

A chave cdn irá prefixar seu pacote de assets e ficará disponível no contexto para que você possa manualmente prefixar outros ativos.

-

A chave protocol é "http" no modo de desenvolvimento e "https" e no modo produção por predefinição.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({project}) {
-    project.name = 'Nullstack';
-    project.shortName = 'Nullstack';
-    project.domain = 'nullstack.app';
-    project.color = '#d22365';
-    project.backgroundColor = '#d22365';
-    project.type = 'website';
-    project.display = 'standalone';
-    project.orientation = 'portrait';
-    project.scope = '/';
-    project.root = '/';
-    project.icons = {
-      '72': '/icon-72x72.png',
-      '128': '/icon-128x128.png',
-      '512': '/icon-512x512.png'
-    };
-    project.favicon = '/favicon.png';
-    project.disallow = ['/admin'];
-    project.sitemap = true;
-    project.cdn = 'cdn.nullstack.app';
-    project.protocol = 'https';
-  }
-
-  prepare({project, page}) {
-    page.title = project.name;
-  }
-
-}
-
-export default Application;
-
-
-

💡 Você pode substituir o manifest.json gerado automaticamente e robots.txt inserindo o seu próprio arquivo na pasta public

-
-

Próximo Passo

⚔ Aprenda sobre a chave settings do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-project/index.html b/docs/pt-br/contexto-project/index.html deleted file mode 100644 index 91b0f21f..00000000 --- a/docs/pt-br/contexto-project/index.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - Contexto Project - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Project

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite no contexto do server
  • -
  • readonly no contexto do client
  • -
-

Ele te dá informações sobre o manifest do app e algumas metatags.

-

As chaves de project serão usadas para gerar metatags durante a renderização do lado do servidor e devem ser definidas antes que initiate seja resolvido.

-

As chaves de project serão usadas para gerar o manifest do app e devem ser definidas durante a inicialização da aplicação.

-

A chave disallow será usada para gerar o robots.txt e deverá ser definida durante a inicialização da aplicação.

-

As chaves de project serão congeladas após a inicialização da aplicação.

-

As chaves a seguir estão disponíveis no objeto:

-
    -
  • domain: string
  • -
  • name: string
  • -
  • shortName: string
  • -
  • color: string
  • -
  • backgroundColor: string
  • -
  • type: string
  • -
  • display: string
  • -
  • orientation: string
  • -
  • scope: string
  • -
  • root: string
  • -
  • icons: object
  • -
  • favicon: string (url relativo ou absoluto)
  • -
  • disallow: array de string (caminhos relativos)
  • -
  • sitemap: boolean ou string (url relativo ou absoluto)
  • -
  • cdn: string (url absoluto)
  • -
  • protocol: string (http or https)
  • -
-

Além de domain, name and color todas as outras chaves tem padrões sensíveis gerados com base no escopo do aplicativo.

-

Se você não declarar a chave icons, Nullstack irá escanear quaisquer ícones com o nome seguindo o padrão "icon-[LARGURA]x[ALTURA].png" na sua pasta public.

-

Se a chave sitemap estiver definida como true o seu arquivo robots.txt irá apontar o sitemap para https://${project.domain}/sitemap.xml.

-

A chave cdn irá prefixar seu pacote de assets e ficará disponível no contexto para que você possa manualmente prefixar outros ativos.

-

A chave protocol é "http" no modo de desenvolvimento e "https" e no modo produção por predefinição.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({project}) {
-    project.name = 'Nullstack';
-    project.shortName = 'Nullstack';
-    project.domain = 'nullstack.app';
-    project.color = '#d22365';
-    project.backgroundColor = '#d22365';
-    project.type = 'website';
-    project.display = 'standalone';
-    project.orientation = 'portrait';
-    project.scope = '/';
-    project.root = '/';
-    project.icons = {
-      '72': '/icon-72x72.png',
-      '128': '/icon-128x128.png',
-      '512': '/icon-512x512.png'
-    };
-    project.favicon = '/favicon.png';
-    project.disallow = ['/admin'];
-    project.sitemap = true;
-    project.cdn = 'cdn.nullstack.app';
-    project.protocol = 'https';
-  }
-
-  prepare({project, page}) {
-    page.title = project.name;
-  }
-
-}
-
-export default Application;
-
-
-

💡 Você pode substituir o manifest.json gerado automaticamente e robots.txt inserindo o seu próprio arquivo na pasta public

-
-

Próximo Passo

⚔ Aprenda sobre a chave settings do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-project/index.json b/docs/pt-br/contexto-project/index.json deleted file mode 100644 index 15850907..00000000 --- a/docs/pt-br/contexto-project/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Project","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: server/client
  • \n
  • readwrite no contexto do server
  • \n
  • readonly no contexto do client
  • \n
\n

Ele te dá informações sobre o manifest do app e algumas metatags.

\n

As chaves de project serão usadas para gerar metatags durante a renderização do lado do servidor e devem ser definidas antes que initiate seja resolvido.

\n

As chaves de project serão usadas para gerar o manifest do app e devem ser definidas durante a inicialização da aplicação.

\n

A chave disallow será usada para gerar o robots.txt e deverá ser definida durante a inicialização da aplicação.

\n

As chaves de project serão congeladas após a inicialização da aplicação.

\n

As chaves a seguir estão disponíveis no objeto:

\n
    \n
  • domain: string
  • \n
  • name: string
  • \n
  • shortName: string
  • \n
  • color: string
  • \n
  • backgroundColor: string
  • \n
  • type: string
  • \n
  • display: string
  • \n
  • orientation: string
  • \n
  • scope: string
  • \n
  • root: string
  • \n
  • icons: object
  • \n
  • favicon: string (url relativo ou absoluto)
  • \n
  • disallow: array de string (caminhos relativos)
  • \n
  • sitemap: boolean ou string (url relativo ou absoluto)
  • \n
  • cdn: string (url absoluto)
  • \n
  • protocol: string (http or https)
  • \n
\n

Além de domain, name and color todas as outras chaves tem padrões sensíveis gerados com base no escopo do aplicativo.

\n

Se você não declarar a chave icons, Nullstack irá escanear quaisquer ícones com o nome seguindo o padrão "icon-[LARGURA]x[ALTURA].png" na sua pasta public.

\n

Se a chave sitemap estiver definida como true o seu arquivo robots.txt irá apontar o sitemap para https://${project.domain}/sitemap.xml.

\n

A chave cdn irá prefixar seu pacote de assets e ficará disponível no contexto para que você possa manualmente prefixar outros ativos.

\n

A chave protocol é "http" no modo de desenvolvimento e "https" e no modo produção por predefinição.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({project}) {\n    project.name = 'Nullstack';\n    project.shortName = 'Nullstack';\n    project.domain = 'nullstack.app';\n    project.color = '#d22365';\n    project.backgroundColor = '#d22365';\n    project.type = 'website';\n    project.display = 'standalone';\n    project.orientation = 'portrait';\n    project.scope = '/';\n    project.root = '/';\n    project.icons = {\n      '72': '/icon-72x72.png',\n      '128': '/icon-128x128.png',\n      '512': '/icon-512x512.png'\n    };\n    project.favicon = '/favicon.png';\n    project.disallow = ['/admin'];\n    project.sitemap = true;\n    project.cdn = 'cdn.nullstack.app';\n    project.protocol = 'https';\n  }\n\n  prepare({project, page}) {\n    page.title = project.name;\n  }\n\n}\n\nexport default Application;\n
\n
\n

💡 Você pode substituir o manifest.json gerado automaticamente e robots.txt inserindo o seu próprio arquivo na pasta public

\n
\n

Próximo Passo

⚔ Aprenda sobre a chave settings do contexto.

\n","description":"O objeto project é um proxy no Contexto Nullstack disponível em ambos client e server e te dá informações sobre o manifest do app e algumas metatags"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Project - Nullstack","description":"O objeto project é um proxy no Contexto Nullstack disponível em ambos client e server e te dá informações sobre o manifest do app e algumas metatags"}} \ No newline at end of file diff --git a/docs/pt-br/contexto-secrets.html b/docs/pt-br/contexto-secrets.html deleted file mode 100644 index d37beffb..00000000 --- a/docs/pt-br/contexto-secrets.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Contexto Secrets - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Secrets

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server
  • -
  • readwrite no contexto do server
  • -
-

Você pode usá-lo para configurar dados sensíveis para sua aplicação.

-

Chaves de secrets são congeladas depois da inicialização da aplicação.

-

As seguintes chaves estão disponíveis no objeto:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [qualquerSegredo]: any
  • -
-

Você pode definir chaves diferentes para as chaves development e production, obtendo assim valores diferentes para cada ambiente.

-

Caso uma chave seja definida diretamente no objeto secrets ela ficará disponível para ambos os ambientes.

-

A leitura das chaves deve ser feita diretamente do objeto secrets, pois o Nullstack vai retornar o valor referido de acordo com o ambiente.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({secrets}) {
-    secrets.development.privateKey = 'SANDBOX_API_KEY';
-    secrets.production.privateKey = 'PRODUCTION_API_KEY';
-    secrets.endpoint = 'https://domain.com/api';
-  }
-
-  static async fetchFromApi({secrets}) {
-    const response = await fetch(secrets.endpoint, {
-      headers: {
-        Authorization: `Bearer ${secrets.privateKey}`
-      }
-    });
-    return await response.json();
-  }
-
-}
-
-export default Application;
-
-

Qualquer chave de ambiente iniciada por NULLSTACK_SECRETS_ será mapeada para o secrets de seu respectivo ambiente.

-
-

🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY será mapeada para secrets.privateKey

-
-

Próximo passo

⚔ Aprendendo sobre o self da instância.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-secrets/index.html b/docs/pt-br/contexto-secrets/index.html deleted file mode 100644 index d37beffb..00000000 --- a/docs/pt-br/contexto-secrets/index.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Contexto Secrets - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Secrets

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server
  • -
  • readwrite no contexto do server
  • -
-

Você pode usá-lo para configurar dados sensíveis para sua aplicação.

-

Chaves de secrets são congeladas depois da inicialização da aplicação.

-

As seguintes chaves estão disponíveis no objeto:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [qualquerSegredo]: any
  • -
-

Você pode definir chaves diferentes para as chaves development e production, obtendo assim valores diferentes para cada ambiente.

-

Caso uma chave seja definida diretamente no objeto secrets ela ficará disponível para ambos os ambientes.

-

A leitura das chaves deve ser feita diretamente do objeto secrets, pois o Nullstack vai retornar o valor referido de acordo com o ambiente.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({secrets}) {
-    secrets.development.privateKey = 'SANDBOX_API_KEY';
-    secrets.production.privateKey = 'PRODUCTION_API_KEY';
-    secrets.endpoint = 'https://domain.com/api';
-  }
-
-  static async fetchFromApi({secrets}) {
-    const response = await fetch(secrets.endpoint, {
-      headers: {
-        Authorization: `Bearer ${secrets.privateKey}`
-      }
-    });
-    return await response.json();
-  }
-
-}
-
-export default Application;
-
-

Qualquer chave de ambiente iniciada por NULLSTACK_SECRETS_ será mapeada para o secrets de seu respectivo ambiente.

-
-

🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY será mapeada para secrets.privateKey

-
-

Próximo passo

⚔ Aprendendo sobre o self da instância.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-secrets/index.json b/docs/pt-br/contexto-secrets/index.json deleted file mode 100644 index 3cdaa1b4..00000000 --- a/docs/pt-br/contexto-secrets/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Secrets","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: server
  • \n
  • readwrite no contexto do server
  • \n
\n

Você pode usá-lo para configurar dados sensíveis para sua aplicação.

\n

Chaves de secrets são congeladas depois da inicialização da aplicação.

\n

As seguintes chaves estão disponíveis no objeto:

\n
    \n
  • development: object
  • \n
  • production: object
  • \n
  • [qualquerSegredo]: any
  • \n
\n

Você pode definir chaves diferentes para as chaves development e production, obtendo assim valores diferentes para cada ambiente.

\n

Caso uma chave seja definida diretamente no objeto secrets ela ficará disponível para ambos os ambientes.

\n

A leitura das chaves deve ser feita diretamente do objeto secrets, pois o Nullstack vai retornar o valor referido de acordo com o ambiente.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({secrets}) {\n    secrets.development.privateKey = 'SANDBOX_API_KEY';\n    secrets.production.privateKey = 'PRODUCTION_API_KEY';\n    secrets.endpoint = 'https://domain.com/api';\n  }\n\n  static async fetchFromApi({secrets}) {\n    const response = await fetch(secrets.endpoint, {\n      headers: {\n        Authorization: `Bearer ${secrets.privateKey}`\n      }\n    });\n    return await response.json();\n  }\n\n}\n\nexport default Application;\n
\n

Qualquer chave de ambiente iniciada por NULLSTACK_SECRETS_ será mapeada para o secrets de seu respectivo ambiente.

\n
\n

🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY será mapeada para secrets.privateKey

\n
\n

Próximo passo

⚔ Aprendendo sobre o self da instância.

\n","description":"O objeto secrets é um proxy no Contexto Nullstack disponível no server que você pode usar para configurar dados sensíveis para sua aplicação"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Secrets - Nullstack","description":"O objeto secrets é um proxy no Contexto Nullstack disponível no server que você pode usar para configurar dados sensíveis para sua aplicação"}} \ No newline at end of file diff --git a/docs/pt-br/contexto-settings.html b/docs/pt-br/contexto-settings.html deleted file mode 100644 index 5d45de44..00000000 --- a/docs/pt-br/contexto-settings.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - Contexto Settings - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Settings

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite no contexto do server
  • -
  • readonly no contexto do client
  • -
-

Você pode usá-lo para configurar seu aplicativo com informações públicas.

-

Chaves de settings serão congeladas após a inicialização do aplicativo.

-

As chaves a seguir estão disponíveis no objeto:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [anySetting]: any
  • -
-

Você pode declarar as chaves para as chaves development ou production para ter diferentes configurações por ambiente.

-

Se você declarar uma chave diretamente para o objeto settings ela ficará disponível em ambos os ambientes.

-

Quando lendo de uma chave você deve ler diretamente do objeto settings e o Nullstack retornará o valor mais adequado para aquele ambiente.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({settings}) {
-    settings.development.publicKey = 'SANDBOX_API_KEY';
-    settings.production.publicKey = 'PRODUCTION_API_KEY';
-    settings.endpoint = 'https://domain.com/api';
-  }
-
-  async hydrate({settings}) {
-    const response = await fetch(settings.endpoint, {
-      headers: {
-        Authorization: `Bearer ${settings.publicKey}`
-      }
-    });
-    this.data = await response.json();
-  }
-
-}
-
-export default Application;
-
-

Qualquer chave de ambiente começando com NULLSTACK_SETTINGS_ será mapeado para as confirgurações daquele ambiente.

-
-

🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY será mapeado para settings.publicKey

-
-

Próximo passo

⚔ Aprenda sobre a chave secrets do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-settings/index.html b/docs/pt-br/contexto-settings/index.html deleted file mode 100644 index 5d45de44..00000000 --- a/docs/pt-br/contexto-settings/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - Contexto Settings - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Settings

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite no contexto do server
  • -
  • readonly no contexto do client
  • -
-

Você pode usá-lo para configurar seu aplicativo com informações públicas.

-

Chaves de settings serão congeladas após a inicialização do aplicativo.

-

As chaves a seguir estão disponíveis no objeto:

-
    -
  • development: object
  • -
  • production: object
  • -
  • [anySetting]: any
  • -
-

Você pode declarar as chaves para as chaves development ou production para ter diferentes configurações por ambiente.

-

Se você declarar uma chave diretamente para o objeto settings ela ficará disponível em ambos os ambientes.

-

Quando lendo de uma chave você deve ler diretamente do objeto settings e o Nullstack retornará o valor mais adequado para aquele ambiente.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({settings}) {
-    settings.development.publicKey = 'SANDBOX_API_KEY';
-    settings.production.publicKey = 'PRODUCTION_API_KEY';
-    settings.endpoint = 'https://domain.com/api';
-  }
-
-  async hydrate({settings}) {
-    const response = await fetch(settings.endpoint, {
-      headers: {
-        Authorization: `Bearer ${settings.publicKey}`
-      }
-    });
-    this.data = await response.json();
-  }
-
-}
-
-export default Application;
-
-

Qualquer chave de ambiente começando com NULLSTACK_SETTINGS_ será mapeado para as confirgurações daquele ambiente.

-
-

🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY será mapeado para settings.publicKey

-
-

Próximo passo

⚔ Aprenda sobre a chave secrets do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto-settings/index.json b/docs/pt-br/contexto-settings/index.json deleted file mode 100644 index 5c57a949..00000000 --- a/docs/pt-br/contexto-settings/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Settings","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: server/client
  • \n
  • readwrite no contexto do server
  • \n
  • readonly no contexto do client
  • \n
\n

Você pode usá-lo para configurar seu aplicativo com informações públicas.

\n

Chaves de settings serão congeladas após a inicialização do aplicativo.

\n

As chaves a seguir estão disponíveis no objeto:

\n
    \n
  • development: object
  • \n
  • production: object
  • \n
  • [anySetting]: any
  • \n
\n

Você pode declarar as chaves para as chaves development ou production para ter diferentes configurações por ambiente.

\n

Se você declarar uma chave diretamente para o objeto settings ela ficará disponível em ambos os ambientes.

\n

Quando lendo de uma chave você deve ler diretamente do objeto settings e o Nullstack retornará o valor mais adequado para aquele ambiente.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({settings}) {\n    settings.development.publicKey = 'SANDBOX_API_KEY';\n    settings.production.publicKey = 'PRODUCTION_API_KEY';\n    settings.endpoint = 'https://domain.com/api';\n  }\n\n  async hydrate({settings}) {\n    const response = await fetch(settings.endpoint, {\n      headers: {\n        Authorization: `Bearer ${settings.publicKey}`\n      }\n    });\n    this.data = await response.json();\n  }\n\n}\n\nexport default Application;\n
\n

Qualquer chave de ambiente começando com NULLSTACK_SETTINGS_ será mapeado para as confirgurações daquele ambiente.

\n
\n

🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY será mapeado para settings.publicKey

\n
\n

Próximo passo

⚔ Aprenda sobre a chave secrets do contexto.

\n","description":"O objeto settings é um proxy no Contexto Nullstack disponível em ambos client e server que você pode usar para configurar seu aplicativo com informações públicas"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Settings - Nullstack","description":"O objeto settings é um proxy no Contexto Nullstack disponível em ambos client e server que você pode usar para configurar seu aplicativo com informações públicas"}} \ No newline at end of file diff --git a/docs/pt-br/contexto.html b/docs/pt-br/contexto.html deleted file mode 100644 index 55ba86eb..00000000 --- a/docs/pt-br/contexto.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - Contexto - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto

Cada função no Nullstack recebe um contexto como argumento.

-

Existem dois contextos, um para o cliente e outro para o servidor.

-

O contexto do cliente dura enquanto a guia do navegador estiver aberta.

-

O contexto do servidor dura enquanto o servidor estiver em execução.

-

Ambos os contextos são proxies que mesclam as chaves de 3 objetos:

-

1 - Contexto Nullstack

Essas são as informações que o framework disponibiliza para você por padrão.

-

As chaves globais disponíveis em ambos server e client são:

-

As chaves disponíveis apenas em funções do servidor são:

-

As chaves de instância do cliente são:

-

2 - Contexto Aplicação

Quando você define uma chave para o contexto, ela fica disponível para desestruturação em qualquer profundidade da aplicação, até mesmo para os objetos pais ou aplicações de terceiros que montam seu componente.

-

Atualizar uma chave no contexto faz com que a aplicação seja renderizada novamente automaticamente.

-

Você pode pensar nisso como um único conceito para substituir stores, contexts, services, e reducers ao mesmo tempo, usando o padrão de injeção de dependência com objetos javascript padrão.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  prepare(context) {
-    context.count = 1;
-  }
-
-  static async updateTotalCount(context) {
-    context.totalCount += context.count;
-  }
-
-  async double(context) {
-    context.count += context.count;
-    await this.updateTotalCount();
-  }
-
-  render({count}) {
-    return (
-      <button onclick={this.double}> {count} </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.totalCount = 0;
-  }
-
-  render({count}) {
-    return (
-      <main>
-        {(!count || count < 10) && <Counter />}
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

3 - Contexto Componente

Este contém os atributos que você declara em sua tag, incluindo os data.

-

Se o atributo é declarado em uma tag componente cada função desse componente terá acesso a esse atributo em seu contexto.

-

Se o atributo for declarado em uma tag que possui um evento, ele será incorporado ao contexto da função de evento.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.delta + context.amount;
-  }
-
-  render({count, delta}) {
-    return (
-      <button onclick={this.add} amount={1}>
-        adicionar {delta} em {count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  prepare(context) {
-    context.count = 0;
-  }
-
-  render() {
-    return (
-      <main>
-        <Counter delta={2} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Contexto de Funções

Cada função das subclasses do Nullstack é injetada com uma cópia do contexto da instância mesclada com seus argumentos.

-

Os argumentos são opcionais, mas se declarados, devem ser um único objeto com chaves de sua escolha.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.amount || 1;
-  }
-
-  prepare(context) {
-    context.count = 0;
-    this.add();            // soma 1
-    this.add({amount: 2}); // soma 2
-  }
-
-  async initiate(context) {
-    console.log(context.count); // 3
-  }
-
-}
-
-export default Counter;
-
-

Próximo passo

⚔ Aprenda sobre Rotas e Parâmetros.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto/index.html b/docs/pt-br/contexto/index.html deleted file mode 100644 index 55ba86eb..00000000 --- a/docs/pt-br/contexto/index.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - Contexto - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto

Cada função no Nullstack recebe um contexto como argumento.

-

Existem dois contextos, um para o cliente e outro para o servidor.

-

O contexto do cliente dura enquanto a guia do navegador estiver aberta.

-

O contexto do servidor dura enquanto o servidor estiver em execução.

-

Ambos os contextos são proxies que mesclam as chaves de 3 objetos:

-

1 - Contexto Nullstack

Essas são as informações que o framework disponibiliza para você por padrão.

-

As chaves globais disponíveis em ambos server e client são:

-

As chaves disponíveis apenas em funções do servidor são:

-

As chaves de instância do cliente são:

-

2 - Contexto Aplicação

Quando você define uma chave para o contexto, ela fica disponível para desestruturação em qualquer profundidade da aplicação, até mesmo para os objetos pais ou aplicações de terceiros que montam seu componente.

-

Atualizar uma chave no contexto faz com que a aplicação seja renderizada novamente automaticamente.

-

Você pode pensar nisso como um único conceito para substituir stores, contexts, services, e reducers ao mesmo tempo, usando o padrão de injeção de dependência com objetos javascript padrão.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  prepare(context) {
-    context.count = 1;
-  }
-
-  static async updateTotalCount(context) {
-    context.totalCount += context.count;
-  }
-
-  async double(context) {
-    context.count += context.count;
-    await this.updateTotalCount();
-  }
-
-  render({count}) {
-    return (
-      <button onclick={this.double}> {count} </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.totalCount = 0;
-  }
-
-  render({count}) {
-    return (
-      <main>
-        {(!count || count < 10) && <Counter />}
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

3 - Contexto Componente

Este contém os atributos que você declara em sua tag, incluindo os data.

-

Se o atributo é declarado em uma tag componente cada função desse componente terá acesso a esse atributo em seu contexto.

-

Se o atributo for declarado em uma tag que possui um evento, ele será incorporado ao contexto da função de evento.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.delta + context.amount;
-  }
-
-  render({count, delta}) {
-    return (
-      <button onclick={this.add} amount={1}>
-        adicionar {delta} em {count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  prepare(context) {
-    context.count = 0;
-  }
-
-  render() {
-    return (
-      <main>
-        <Counter delta={2} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Contexto de Funções

Cada função das subclasses do Nullstack é injetada com uma cópia do contexto da instância mesclada com seus argumentos.

-

Os argumentos são opcionais, mas se declarados, devem ser um único objeto com chaves de sua escolha.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  add(context) {
-    context.count += context.amount || 1;
-  }
-
-  prepare(context) {
-    context.count = 0;
-    this.add();            // soma 1
-    this.add({amount: 2}); // soma 2
-  }
-
-  async initiate(context) {
-    console.log(context.count); // 3
-  }
-
-}
-
-export default Counter;
-
-

Próximo passo

⚔ Aprenda sobre Rotas e Parâmetros.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/contexto/index.json b/docs/pt-br/contexto/index.json deleted file mode 100644 index b3c28632..00000000 --- a/docs/pt-br/contexto/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto","html":"

Cada função no Nullstack recebe um contexto como argumento.

\n

Existem dois contextos, um para o cliente e outro para o servidor.

\n

O contexto do cliente dura enquanto a guia do navegador estiver aberta.

\n

O contexto do servidor dura enquanto o servidor estiver em execução.

\n

Ambos os contextos são proxies que mesclam as chaves de 3 objetos:

\n

1 - Contexto Nullstack

Essas são as informações que o framework disponibiliza para você por padrão.

\n

As chaves globais disponíveis em ambos server e client são:

\n

As chaves disponíveis apenas em funções do servidor são:

\n

As chaves de instância do cliente são:

\n

2 - Contexto Aplicação

Quando você define uma chave para o contexto, ela fica disponível para desestruturação em qualquer profundidade da aplicação, até mesmo para os objetos pais ou aplicações de terceiros que montam seu componente.

\n

Atualizar uma chave no contexto faz com que a aplicação seja renderizada novamente automaticamente.

\n

Você pode pensar nisso como um único conceito para substituir stores, contexts, services, e reducers ao mesmo tempo, usando o padrão de injeção de dependência com objetos javascript padrão.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  prepare(context) {\n    context.count = 1;\n  }\n\n  static async updateTotalCount(context) {\n    context.totalCount += context.count;\n  }\n\n  async double(context) {\n    context.count += context.count;\n    await this.updateTotalCount();\n  }\n\n  render({count}) {\n    return (\n      <button onclick={this.double}> {count} </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    context.totalCount = 0;\n  }\n\n  render({count}) {\n    return (\n      <main>\n        {(!count || count < 10) && <Counter />}\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

3 - Contexto Componente

Este contém os atributos que você declara em sua tag, incluindo os data.

\n

Se o atributo é declarado em uma tag componente cada função desse componente terá acesso a esse atributo em seu contexto.

\n

Se o atributo for declarado em uma tag que possui um evento, ele será incorporado ao contexto da função de evento.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  add(context) {\n    context.count += context.delta + context.amount;\n  }\n\n  render({count, delta}) {\n    return (\n      <button onclick={this.add} amount={1}>\n        adicionar {delta} em {count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  prepare(context) {\n    context.count = 0;\n  }\n\n  render() {\n    return (\n      <main>\n        <Counter delta={2} />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Contexto de Funções

Cada função das subclasses do Nullstack é injetada com uma cópia do contexto da instância mesclada com seus argumentos.

\n

Os argumentos são opcionais, mas se declarados, devem ser um único objeto com chaves de sua escolha.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  add(context) {\n    context.count += context.amount || 1;\n  }\n\n  prepare(context) {\n    context.count = 0;\n    this.add();            // soma 1\n    this.add({amount: 2}); // soma 2\n  }\n\n  async initiate(context) {\n    console.log(context.count); // 3\n  }\n\n}\n\nexport default Counter;\n
\n

Próximo passo

⚔ Aprenda sobre Rotas e Parâmetros.

\n","description":"Cada função no Nullstack recebe um contexto como argumento."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto - Nullstack","description":"Cada função no Nullstack recebe um contexto como argumento."}} \ No newline at end of file diff --git a/docs/pt-br/contribuidores.html b/docs/pt-br/contribuidores.html deleted file mode 100644 index 8765aa04..00000000 --- a/docs/pt-br/contribuidores.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Contribuidores - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

O Estado do Nullstack

O Nullstack está sendo desenvolvido desde janeiro de 2019 com recursos sendo extraídos de projetos freelance.

Nesse ponto, a API está estável, os métodos de ciclo de vida e as chaves de contexto estarão praticamente congelados.

Ainda não estamos na v1.0, mas muito perto, a única coisa que falta é testá-lo em aplicativos feitos fora da equipe principal para descobrir se ele atende às necessidades de outros programadores.

O Mapa da Estrada

As próximas atualizações serão direcionadas a correções de quaisquer bugs encontrados e terão foco na qualidade de vida.

As atualizações listadas nas issues do Nullstack são as próximas etapas planejadas sem nenhuma ordem específica.

A Equipe Principal

O Nullstack foi desenvolvido por freelancers full-stacks neuroatípicos.

Com um histórico pesado em Rails, Ember.js, React.js e filosofia Vue.js as inspirações tiradas desses projetos podem ser óbvias.

Christian Mortaro

Christian Mortaro

Autor Autista

Criador do conceito. Vai com novas propostas de API para seus patos de borracha favoritos e retorna com commits.

Fez a engenharia reversa de código de pensamento positivo para sua existência e depois o refatorou em um framework.

Dayson Marx

Dayson Marx

Designer Distraído

Pato de borracha com habilidades humanas, garante que o código não saia muito pra fora da caixa, então faz a caixa parecer legal.

Revisor de API que desenvolveu projetos de terceiros para testar a prova de conceitos de uma perspectiva focada no front-end.

Anny Figueira

Anny Figueira

Adotante Autista

Pato de borracha com um pescoço para encontrar inconsistências e problemas, esperando até que uma API seja aprovada para nos forçar a reescrever tudo.

Adotante antecipada do framework que desenvolveu aplicações reais em produção para validar como as partes se encaixam.

Bianca Augusta

Bianca Augusta

Artista Autista

Ilustradora freelancer faz 10 anos. Viciada em Warcraft, aspirante a cosplayer e druida tanker no WoW.

Mamãe da Nulla-Chan e volta e meia lê scripts por pura pressão do Mortaro.

Guilherme Correia

Guilherme Correia

import Membro from vuejs-br

Experimentalista, escritor de universos, sonhador e desenvolvedor quando acha e toca a fita K7 sem título certa.

Usuário de features não documentadas e criador de issues exigindo documentação que ele mesmo vai fazer.

Alisson Suassuna

Alisson Suassuna

Servo de Deus

Instrutor da TipsCode. Desenvolvedor Full-stack JavaScript, apaixonado por tecnologia e servo do Senhor Jesus Cristo.

Encarregado da criação de conteúdo sobre o Nullstack, aulas, dicas e tutoriais. Com objetivo de tornar o Nullstack fácil de usar.

Contribuidores dos Pacotes

* A lista pode demorar um pouco para ser atualizada devido ao cache da API do GitHub

Contribuidores da Documentação

* A lista pode demorar um pouco para ser atualizada devido ao cache da API do GitHub

Como Contribuir

É simples. Encontrou um bug ou deseja um novo recurso?

Crie uma issue ou envie uma pull request com testes.

- - - \ No newline at end of file diff --git a/docs/pt-br/contribuidores/index.html b/docs/pt-br/contribuidores/index.html deleted file mode 100644 index 8765aa04..00000000 --- a/docs/pt-br/contribuidores/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Contribuidores - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

O Estado do Nullstack

O Nullstack está sendo desenvolvido desde janeiro de 2019 com recursos sendo extraídos de projetos freelance.

Nesse ponto, a API está estável, os métodos de ciclo de vida e as chaves de contexto estarão praticamente congelados.

Ainda não estamos na v1.0, mas muito perto, a única coisa que falta é testá-lo em aplicativos feitos fora da equipe principal para descobrir se ele atende às necessidades de outros programadores.

O Mapa da Estrada

As próximas atualizações serão direcionadas a correções de quaisquer bugs encontrados e terão foco na qualidade de vida.

As atualizações listadas nas issues do Nullstack são as próximas etapas planejadas sem nenhuma ordem específica.

A Equipe Principal

O Nullstack foi desenvolvido por freelancers full-stacks neuroatípicos.

Com um histórico pesado em Rails, Ember.js, React.js e filosofia Vue.js as inspirações tiradas desses projetos podem ser óbvias.

Christian Mortaro

Christian Mortaro

Autor Autista

Criador do conceito. Vai com novas propostas de API para seus patos de borracha favoritos e retorna com commits.

Fez a engenharia reversa de código de pensamento positivo para sua existência e depois o refatorou em um framework.

Dayson Marx

Dayson Marx

Designer Distraído

Pato de borracha com habilidades humanas, garante que o código não saia muito pra fora da caixa, então faz a caixa parecer legal.

Revisor de API que desenvolveu projetos de terceiros para testar a prova de conceitos de uma perspectiva focada no front-end.

Anny Figueira

Anny Figueira

Adotante Autista

Pato de borracha com um pescoço para encontrar inconsistências e problemas, esperando até que uma API seja aprovada para nos forçar a reescrever tudo.

Adotante antecipada do framework que desenvolveu aplicações reais em produção para validar como as partes se encaixam.

Bianca Augusta

Bianca Augusta

Artista Autista

Ilustradora freelancer faz 10 anos. Viciada em Warcraft, aspirante a cosplayer e druida tanker no WoW.

Mamãe da Nulla-Chan e volta e meia lê scripts por pura pressão do Mortaro.

Guilherme Correia

Guilherme Correia

import Membro from vuejs-br

Experimentalista, escritor de universos, sonhador e desenvolvedor quando acha e toca a fita K7 sem título certa.

Usuário de features não documentadas e criador de issues exigindo documentação que ele mesmo vai fazer.

Alisson Suassuna

Alisson Suassuna

Servo de Deus

Instrutor da TipsCode. Desenvolvedor Full-stack JavaScript, apaixonado por tecnologia e servo do Senhor Jesus Cristo.

Encarregado da criação de conteúdo sobre o Nullstack, aulas, dicas e tutoriais. Com objetivo de tornar o Nullstack fácil de usar.

Contribuidores dos Pacotes

* A lista pode demorar um pouco para ser atualizada devido ao cache da API do GitHub

Contribuidores da Documentação

* A lista pode demorar um pouco para ser atualizada devido ao cache da API do GitHub

Como Contribuir

É simples. Encontrou um bug ou deseja um novo recurso?

Crie uma issue ou envie uma pull request com testes.

- - - \ No newline at end of file diff --git a/docs/pt-br/contribuidores/index.json b/docs/pt-br/contribuidores/index.json deleted file mode 100644 index 480c6663..00000000 --- a/docs/pt-br/contribuidores/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-8":{"documentation":[],"packages":[],"locale":"pt-BR","i18n":{"title":"Contribuidores","description":"Encontrou um bug ou deseja uma feature nova? Torne-se um contribuidor!","state":{"title":"O Estado do Nullstack","paragraphs":["O Nullstack está sendo desenvolvido desde janeiro de 2019 com recursos sendo extraídos de projetos freelance.","Nesse ponto, a API está estável, os métodos de ciclo de vida e as chaves de contexto estarão praticamente congelados.","Ainda não estamos na v1.0, mas muito perto, a única coisa que falta é testá-lo em aplicativos feitos fora da equipe principal para descobrir se ele atende às necessidades de outros programadores."]},"roadmap":{"title":"O Mapa da Estrada","paragraphs":["As próximas atualizações serão direcionadas a correções de quaisquer bugs encontrados e terão foco na qualidade de vida.","As atualizações listadas nas issues do Nullstack são as próximas etapas planejadas sem nenhuma ordem específica."]},"core":{"title":"A Equipe Principal","paragraphs":["O Nullstack foi desenvolvido por freelancers full-stacks neuroatípicos.","Com um histórico pesado em Rails, Ember.js, React.js e filosofia Vue.js as inspirações tiradas desses projetos podem ser óbvias."],"team":[{"name":"Christian Mortaro","role":"Autor Autista","github":"Mortaro","description":"Criador do conceito. Vai com novas propostas de API para seus patos de borracha favoritos e retorna com commits.","contribution":"Fez a engenharia reversa de código de pensamento positivo para sua existência e depois o refatorou em um framework."},{"name":"Dayson Marx","role":"Designer Distraído","github":"daysonmarx","description":"Pato de borracha com habilidades humanas, garante que o código não saia muito pra fora da caixa, então faz a caixa parecer legal.","contribution":"Revisor de API que desenvolveu projetos de terceiros para testar a prova de conceitos de uma perspectiva focada no front-end."},{"name":"Anny Figueira","role":"Adotante Autista","github":"AnnyFigueira","description":"Pato de borracha com um pescoço para encontrar inconsistências e problemas, esperando até que uma API seja aprovada para nos forçar a reescrever tudo.","contribution":"Adotante antecipada do framework que desenvolveu aplicações reais em produção para validar como as partes se encaixam."},{"name":"Bianca Augusta","role":"Artista Autista","github":"Bilkaya","description":"Ilustradora freelancer faz 10 anos. Viciada em Warcraft, aspirante a cosplayer e druida tanker no WoW.","contribution":"Mamãe da Nulla-Chan e volta e meia lê scripts por pura pressão do Mortaro."},{"name":"Guilherme Correia","role":"import Membro from vuejs-br","github":"GuiDevloper","description":"Experimentalista, escritor de universos, sonhador e desenvolvedor quando acha e toca a fita K7 sem título certa.","contribution":"Usuário de features não documentadas e criador de issues exigindo documentação que ele mesmo vai fazer."},{"name":"Alisson Suassuna","role":"Servo de Deus","github":"alissonsuassuna","description":"Instrutor da TipsCode. Desenvolvedor Full-stack JavaScript, apaixonado por tecnologia e servo do Senhor Jesus Cristo.","contribution":"Encarregado da criação de conteúdo sobre o Nullstack, aulas, dicas e tutoriais. Com objetivo de tornar o Nullstack fácil de usar."}]},"packages":{"title":"Contribuidores dos Pacotes"},"documentation":{"title":"Contribuidores da Documentação"},"instructions":{"title":"Como Contribuir","paragraphs":["É simples. Encontrou um bug ou deseja um novo recurso?","Crie uma issue ou envie uma pull request com testes."]},"githubCacheWarning":"* A lista pode demorar um pouco para ser atualizada devido ao cache da API do GitHub"}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contribuidores - Nullstack","description":"Encontrou um bug ou deseja uma feature nova? Torne-se um contribuidor!","locale":"pt-BR"}} \ No newline at end of file diff --git a/docs/pt-br/documentacao.html b/docs/pt-br/documentacao.html deleted file mode 100644 index 1b082303..00000000 --- a/docs/pt-br/documentacao.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Documentação - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/pt-br/documentacao/index.html b/docs/pt-br/documentacao/index.html deleted file mode 100644 index 1b082303..00000000 --- a/docs/pt-br/documentacao/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Documentação - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/pt-br/documentacao/index.json b/docs/pt-br/documentacao/index.json deleted file mode 100644 index 5b290377..00000000 --- a/docs/pt-br/documentacao/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-4":{"locale":"pt-BR","i18n":{"title":"Documentação","description":"Siga esses passos e se torne um desenvolvedor full-stack javascript!","heading":"Documentação do Nullstack","tagline":"Siga esses passos e se torne um desenvolvedor full-stack javascript!","topics":[{"title":"Principais conceitos","description":"Comece sua jornada no Nullstack com estes conceitos básicos","links":[{"title":"Começando","href":"/pt-br/comecando"},{"title":"Componentes renderizáveis","href":"/pt-br/componentes-renderizaveis"},{"title":"Componentes com estado","href":"/pt-br/componentes-com-estado"},{"title":"Ciclo de vida full-stack","href":"/pt-br/ciclo-de-vida-full-stack"},{"title":"Funções de servidor","href":"/pt-br/funcoes-de-servidor"},{"title":"Contexto","href":"/pt-br/contexto"},{"title":"Rotas e parâmetros","href":"/pt-br/rotas-e-parametros"},{"title":"Vínculo bidirecional","href":"/pt-br/vinculo-bidirecional"}]},{"title":"Conceitos avançados","description":"Estes são conceitos que você provavelmente aprenderá conforme precisar em seus projetos","links":[{"title":"Inicialização da aplicação","href":"/pt-br/inicializacao-da-aplicacao"},{"title":"Contexto data","href":"/pt-br/contexto-data"},{"title":"Contexto Environment","href":"/pt-br/contexto-environment"},{"title":"Contexto Page","href":"/pt-br/contexto-page"},{"title":"Contexto Project","href":"/pt-br/contexto-project"},{"title":"Contexto Settings","href":"/pt-br/contexto-settings"},{"title":"Contexto Secrets","href":"/pt-br/contexto-secrets"},{"title":"self da Instância","href":"/pt-br/instancia-self"},{"title":"Requisição e resposta do servidor","href":"/pt-br/requisicao-e-resposta-do-servidor"},{"title":"Estilos","href":"/pt-br/estilos"},{"title":"Extensão de arquivo NJS","href":"/pt-br/extensao-de-arquivo-njs"},{"title":"Renderizando no servidor","href":"/pt-br/renderizando-no-servidor"},{"title":"Geração de sites estáticos","href":"/pt-br/geracao-de-sites-estaticos"},{"title":"Service Worker","href":"/pt-br/service-worker"},{"title":"Como fazer deploy de aplicação Nullstack","href":"/pt-br/como-fazer-deploy-de-aplicacao-nullstack"}]},{"title":"Exemplos","description":"A melhor maneira de aprender Nullstack é lendo algum código","links":[{"title":"Como usar MongoDB com Nullstack","href":"/pt-br/como-usar-mongodb-com-nullstack"},{"title":"Como usar Google Analytics no Nullstack","href":"/pt-br/como-usar-google-analytics-no-nullstack"},{"title":"Como usar Facebook Pixel no Nullstack","href":"/pt-br/como-usar-facebook-pixel-no-nullstack"}]}]}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"priority":0.8,"title":"Documentação - Nullstack","description":"Siga esses passos e se torne um desenvolvedor full-stack javascript!","locale":"pt-BR"}} \ No newline at end of file diff --git a/docs/pt-br/estilos.html b/docs/pt-br/estilos.html deleted file mode 100644 index 56b690f8..00000000 --- a/docs/pt-br/estilos.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - Estilos - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Estilos

Usar estilos com o Nullstack é tão simples quanto importar um arquivo de estilo.

-

O Nullstack vem com um loader SASS por padrão, mas você ainda pode usar o CSS Vanilla.

-
-

✨ É uma boa prática importar um arquivo com o mesmo nome do componente.

-
-
import Nullstack from 'nullstack';
-import './Header.scss';
-
-class Header extends Nullstack {
-  // ...
-}
-
-export default Header;
-
-

No modo de produção, o Nullstack usa PurgeCSS, que limpa seu arquivo client.css, mas tem alguns truques.

-
-

✨ Saiba mais sobre fazendo uma safelist do seu css

-
-

Próximo passo

⚔ Aprenda sobre a extensão de arquivo NJS.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/estilos/index.html b/docs/pt-br/estilos/index.html deleted file mode 100644 index 56b690f8..00000000 --- a/docs/pt-br/estilos/index.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - Estilos - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Estilos

Usar estilos com o Nullstack é tão simples quanto importar um arquivo de estilo.

-

O Nullstack vem com um loader SASS por padrão, mas você ainda pode usar o CSS Vanilla.

-
-

✨ É uma boa prática importar um arquivo com o mesmo nome do componente.

-
-
import Nullstack from 'nullstack';
-import './Header.scss';
-
-class Header extends Nullstack {
-  // ...
-}
-
-export default Header;
-
-

No modo de produção, o Nullstack usa PurgeCSS, que limpa seu arquivo client.css, mas tem alguns truques.

-
-

✨ Saiba mais sobre fazendo uma safelist do seu css

-
-

Próximo passo

⚔ Aprenda sobre a extensão de arquivo NJS.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/estilos/index.json b/docs/pt-br/estilos/index.json deleted file mode 100644 index 4a63f9dd..00000000 --- a/docs/pt-br/estilos/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Estilos","html":"

Usar estilos com o Nullstack é tão simples quanto importar um arquivo de estilo.

\n

O Nullstack vem com um loader SASS por padrão, mas você ainda pode usar o CSS Vanilla.

\n
\n

✨ É uma boa prática importar um arquivo com o mesmo nome do componente.

\n
\n
import Nullstack from 'nullstack';\nimport './Header.scss';\n\nclass Header extends Nullstack {\n  // ...\n}\n\nexport default Header;\n
\n

No modo de produção, o Nullstack usa PurgeCSS, que limpa seu arquivo client.css, mas tem alguns truques.

\n
\n

✨ Saiba mais sobre fazendo uma safelist do seu css

\n
\n

Próximo passo

⚔ Aprenda sobre a extensão de arquivo NJS.

\n","description":"Usar estilos com o Nullstack é tão simples quanto importar um arquivo de estilo."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Estilos - Nullstack","description":"Usar estilos com o Nullstack é tão simples quanto importar um arquivo de estilo."}} \ No newline at end of file diff --git a/docs/pt-br/extensao-de-arquivo-njs.html b/docs/pt-br/extensao-de-arquivo-njs.html deleted file mode 100644 index 580c014e..00000000 --- a/docs/pt-br/extensao-de-arquivo-njs.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - Extensão de arquivos NJS - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Extensão de arquivos NJS

Os arquivos do Nullstack permitem ao Webpack saber quais carregadores usar no momento da transpilação.

-

Os arquivos NJS devem importar o Nullstack ou uma de suas subclasses.

-

Se apenas uma subclasse for importada, uma importação Nullstack será injetada no momento da transpilação.

-

No momento da transpilação, as tags JSX serão substituídas por Nullstack.element.

-

Essa extensão também permite que o Nullstack faça otimizações em tempo de transpilação, como a injeção de origem.

-
-

🔥 Cada arquivo deve ter apenas uma classe declarada.

-
-
    -
  • No bundle server, as funções assíncronas estáticas são mapeadas em um registro para segurança.
  • -
  • No bundle client, as funções assíncronas estáticas são removidas e substituídas por um método invoke.
  • -
  • No bundle client, as funções assíncronas estáticas com o nome começando com "start" (e opcionalmente seguido por uma letra maiúscula) são completamente removidas.
  • -
  • Nos bundles server e client, um hash com o md5 do código-fonte original é adicionado na classe.
  • -
-
-

🐱‍💻 Abaixo um exemplo de arquivo .njs original.

-
-
import List from './List';
-import {readFileSync} from 'fs';
-
-class Tasks extends List {
-
-  static async getTasks({limit}) {
-    const json = readFileSync('tasks.json', 'utf-8');
-    return JSON.parse(json).tasks.slice(0, limit);
-  }
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input bind={task.description} />
-      </li>
-    )
-  }
-
-  render() {
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-
-

🐱‍💻 Abaixo um exemplo do mesmo arquivo .njs transpilado.

-
-
import Nullstack from 'nullstack';
-import List from './List';
-
-class Tasks extends List {
-
-  static hash = 'd493ac09d0d57574a30f136d31da455f';
-
-  static getTasks = Nullstack.invoke('getTasks', 'd493ac09d0d57574a30f136d31da455f');
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input source={task} bind="description" />
-      </li>
-    )
-  }
-
-  render() {
-    const Task = this.renderTask;
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-

Próximo Passo

⚔ Aprenda sobre a renderização no servidor.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/extensao-de-arquivo-njs/index.html b/docs/pt-br/extensao-de-arquivo-njs/index.html deleted file mode 100644 index 580c014e..00000000 --- a/docs/pt-br/extensao-de-arquivo-njs/index.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - Extensão de arquivos NJS - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Extensão de arquivos NJS

Os arquivos do Nullstack permitem ao Webpack saber quais carregadores usar no momento da transpilação.

-

Os arquivos NJS devem importar o Nullstack ou uma de suas subclasses.

-

Se apenas uma subclasse for importada, uma importação Nullstack será injetada no momento da transpilação.

-

No momento da transpilação, as tags JSX serão substituídas por Nullstack.element.

-

Essa extensão também permite que o Nullstack faça otimizações em tempo de transpilação, como a injeção de origem.

-
-

🔥 Cada arquivo deve ter apenas uma classe declarada.

-
-
    -
  • No bundle server, as funções assíncronas estáticas são mapeadas em um registro para segurança.
  • -
  • No bundle client, as funções assíncronas estáticas são removidas e substituídas por um método invoke.
  • -
  • No bundle client, as funções assíncronas estáticas com o nome começando com "start" (e opcionalmente seguido por uma letra maiúscula) são completamente removidas.
  • -
  • Nos bundles server e client, um hash com o md5 do código-fonte original é adicionado na classe.
  • -
-
-

🐱‍💻 Abaixo um exemplo de arquivo .njs original.

-
-
import List from './List';
-import {readFileSync} from 'fs';
-
-class Tasks extends List {
-
-  static async getTasks({limit}) {
-    const json = readFileSync('tasks.json', 'utf-8');
-    return JSON.parse(json).tasks.slice(0, limit);
-  }
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input bind={task.description} />
-      </li>
-    )
-  }
-
-  render() {
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-
-

🐱‍💻 Abaixo um exemplo do mesmo arquivo .njs transpilado.

-
-
import Nullstack from 'nullstack';
-import List from './List';
-
-class Tasks extends List {
-
-  static hash = 'd493ac09d0d57574a30f136d31da455f';
-
-  static getTasks = Nullstack.invoke('getTasks', 'd493ac09d0d57574a30f136d31da455f');
-
-  prepare(context) {
-    context.tasks = [];
-  }
-
-  async initiate(context) {
-    context.tasks = await this.getTasks({limit: 10});
-  }
-
-  renderTask({task}) {
-    return (
-      <li> 
-        <input source={task} bind="description" />
-      </li>
-    )
-  }
-
-  render() {
-    const Task = this.renderTask;
-    return (
-      <main>
-        <ul>
-          {tasks.map((task) => <Task task={task} />)}
-        </ul>
-      </main>
-    )
-  }
-
-}
-
-export default Tasks;
-
-

Próximo Passo

⚔ Aprenda sobre a renderização no servidor.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/extensao-de-arquivo-njs/index.json b/docs/pt-br/extensao-de-arquivo-njs/index.json deleted file mode 100644 index 6e99f72a..00000000 --- a/docs/pt-br/extensao-de-arquivo-njs/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Extensão de arquivos NJS","html":"

Os arquivos do Nullstack permitem ao Webpack saber quais carregadores usar no momento da transpilação.

\n

Os arquivos NJS devem importar o Nullstack ou uma de suas subclasses.

\n

Se apenas uma subclasse for importada, uma importação Nullstack será injetada no momento da transpilação.

\n

No momento da transpilação, as tags JSX serão substituídas por Nullstack.element.

\n

Essa extensão também permite que o Nullstack faça otimizações em tempo de transpilação, como a injeção de origem.

\n
\n

🔥 Cada arquivo deve ter apenas uma classe declarada.

\n
\n
    \n
  • No bundle server, as funções assíncronas estáticas são mapeadas em um registro para segurança.
  • \n
  • No bundle client, as funções assíncronas estáticas são removidas e substituídas por um método invoke.
  • \n
  • No bundle client, as funções assíncronas estáticas com o nome começando com "start" (e opcionalmente seguido por uma letra maiúscula) são completamente removidas.
  • \n
  • Nos bundles server e client, um hash com o md5 do código-fonte original é adicionado na classe.
  • \n
\n
\n

🐱‍💻 Abaixo um exemplo de arquivo .njs original.

\n
\n
import List from './List';\nimport {readFileSync} from 'fs';\n\nclass Tasks extends List {\n\n  static async getTasks({limit}) {\n    const json = readFileSync('tasks.json', 'utf-8');\n    return JSON.parse(json).tasks.slice(0, limit);\n  }\n\n  prepare(context) {\n    context.tasks = [];\n  }\n\n  async initiate(context) {\n    context.tasks = await this.getTasks({limit: 10});\n  }\n\n  renderTask({task}) {\n    return (\n      <li> \n        <input bind={task.description} />\n      </li>\n    )\n  }\n\n  render() {\n    return (\n      <main>\n        <ul>\n          {tasks.map((task) => <Task task={task} />)}\n        </ul>\n      </main>\n    )\n  }\n\n}\n\nexport default Tasks;\n
\n
\n

🐱‍💻 Abaixo um exemplo do mesmo arquivo .njs transpilado.

\n
\n
import Nullstack from 'nullstack';\nimport List from './List';\n\nclass Tasks extends List {\n\n  static hash = 'd493ac09d0d57574a30f136d31da455f';\n\n  static getTasks = Nullstack.invoke('getTasks', 'd493ac09d0d57574a30f136d31da455f');\n\n  prepare(context) {\n    context.tasks = [];\n  }\n\n  async initiate(context) {\n    context.tasks = await this.getTasks({limit: 10});\n  }\n\n  renderTask({task}) {\n    return (\n      <li> \n        <input source={task} bind=\"description\" />\n      </li>\n    )\n  }\n\n  render() {\n    const Task = this.renderTask;\n    return (\n      <main>\n        <ul>\n          {tasks.map((task) => <Task task={task} />)}\n        </ul>\n      </main>\n    )\n  }\n\n}\n\nexport default Tasks;\n
\n

Próximo Passo

⚔ Aprenda sobre a renderização no servidor.

\n","description":"Os arquivos Nullstack permitem que o Webpack saiba quais carregadores usar no momento da transpilação"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Extensão de arquivos NJS - Nullstack","description":"Os arquivos Nullstack permitem que o Webpack saiba quais carregadores usar no momento da transpilação"}} \ No newline at end of file diff --git "a/docs/pt-br/extens\303\243o-de-arquivo-njs.html" "b/docs/pt-br/extens\303\243o-de-arquivo-njs.html" deleted file mode 100644 index c29ce87e..00000000 --- "a/docs/pt-br/extens\303\243o-de-arquivo-njs.html" +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Página Não Encontrada - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Página Não Encontrada

- - - \ No newline at end of file diff --git "a/docs/pt-br/extens\303\243o-de-arquivo-njs/index.html" "b/docs/pt-br/extens\303\243o-de-arquivo-njs/index.html" deleted file mode 100644 index c29ce87e..00000000 --- "a/docs/pt-br/extens\303\243o-de-arquivo-njs/index.html" +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Página Não Encontrada - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Página Não Encontrada

- - - \ No newline at end of file diff --git "a/docs/pt-br/extens\303\243o-de-arquivo-njs/index.json" "b/docs/pt-br/extens\303\243o-de-arquivo-njs/index.json" deleted file mode 100644 index b918fadd..00000000 --- "a/docs/pt-br/extens\303\243o-de-arquivo-njs/index.json" +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Página Não Encontrada","html":"

Talvez você queira aprender como criar uma pagina 404 com Nullstack?

\n

Se você está procurando por outra coisa, você deveria ler a documentação.

\n","description":"Desculpe, essa não é a página que você está procurando","status":404},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":404,"title":"Página Não Encontrada - Nullstack","description":"Desculpe, essa não é a página que você está procurando"}} \ No newline at end of file diff --git a/docs/pt-br/funcoes-de-servidor.html b/docs/pt-br/funcoes-de-servidor.html deleted file mode 100644 index e2bee2d1..00000000 --- a/docs/pt-br/funcoes-de-servidor.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - Server Functions - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server Functions

Server functions are specialized microservices that at transpile time are converted into API entry points.

-

To flag a function as a server function, you must declare it as static async.

-

Being a static function means it has no access to the instance scope.

-

However, instead of calling the static version from the class, you must invoke it as an instance function.

-

Server functions can be called anytime in your code and are not limited to prerender steps.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-  }
-
-  async handleClick() {
-    await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Learn more about the server context.

-
-

Client behavior

When you call a server function from the client, the arguments will be serialized as JSON.

-

The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.

-

The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-    return context.count;
-  }
-
-  async handleClick() {
-    this.count = await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server behavior

Server functions will be used as local functions, simply aliasing the instance call to the class and merging the arguments with the server context.

-

Date Convenience

Dates are serialized as UTC in JSON and deserialized back to Date objects.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  async initiate() {
-    const date = new Date();
-    const verified = this.verifyDay({date});
-  }
-
-  static async verifyDay({date}) {
-    return date.getDay() === new Date().getDay();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Fetch Convenience

fetch is available in both server and client functions for the sake of isomorphy.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    const url = 'https://api.github.com/repos/nullstack/nullstack/issues';
-    const response = await fetch(url);
-    this.issues = await response.json();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server only imports

Imported dependencies that are only used inside server functions will be excluded from the client bundle.

-

This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.

-
import Nullstack from 'nullstack';
-import {readFileSync} from 'fs';
-import {Remarkable} from 'remarkable';
-
-class Application extends Nullstack {
-
-  static async getTasks() {
-    const readme = readFileSync('README.md', 'utf-8');
-    return new Remarkable().render(readme);
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Security

Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.

-
-

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

-
-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async getCount({request, count}) {
-    if(!request.session.user) return 0;
-    return count;
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

💡 Server functions are not exposed to the client.

-
-
-

✨ Learn more about the NJS file extension.

-
-

Reserved words

Server function names cannot collide with instance method names from the current class or its parent classes.

-

The following words cannot be used in server functions:

-
    -
  • prepare
  • -
  • initiate
  • -
  • hydrate
  • -
  • update
  • -
  • terminate
  • -
-

Server functions named start will not generate an API endpoint and can only be called by other server functions.

-

Caveats

Automatically generated API endpoints are not meant to be used by 3rd-party apps.

-

The URL and implementation may change between versions of Nullstack.

-
-

✨ If you want to build an API, learn more about how to create an API with Nullstack.

-
-

Next step

⚔ Learn about the context.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/funcoes-de-servidor/index.html b/docs/pt-br/funcoes-de-servidor/index.html deleted file mode 100644 index e2bee2d1..00000000 --- a/docs/pt-br/funcoes-de-servidor/index.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - Server Functions - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server Functions

Server functions are specialized microservices that at transpile time are converted into API entry points.

-

To flag a function as a server function, you must declare it as static async.

-

Being a static function means it has no access to the instance scope.

-

However, instead of calling the static version from the class, you must invoke it as an instance function.

-

Server functions can be called anytime in your code and are not limited to prerender steps.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-  }
-
-  async handleClick() {
-    await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Learn more about the server context.

-
-

Client behavior

When you call a server function from the client, the arguments will be serialized as JSON.

-

The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.

-

The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-    return context.count;
-  }
-
-  async handleClick() {
-    this.count = await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server behavior

Server functions will be used as local functions, simply aliasing the instance call to the class and merging the arguments with the server context.

-

Date Convenience

Dates are serialized as UTC in JSON and deserialized back to Date objects.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  async initiate() {
-    const date = new Date();
-    const verified = this.verifyDay({date});
-  }
-
-  static async verifyDay({date}) {
-    return date.getDay() === new Date().getDay();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Fetch Convenience

fetch is available in both server and client functions for the sake of isomorphy.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    const url = 'https://api.github.com/repos/nullstack/nullstack/issues';
-    const response = await fetch(url);
-    this.issues = await response.json();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server only imports

Imported dependencies that are only used inside server functions will be excluded from the client bundle.

-

This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.

-
import Nullstack from 'nullstack';
-import {readFileSync} from 'fs';
-import {Remarkable} from 'remarkable';
-
-class Application extends Nullstack {
-
-  static async getTasks() {
-    const readme = readFileSync('README.md', 'utf-8');
-    return new Remarkable().render(readme);
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Security

Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.

-
-

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

-
-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async getCount({request, count}) {
-    if(!request.session.user) return 0;
-    return count;
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

💡 Server functions are not exposed to the client.

-
-
-

✨ Learn more about the NJS file extension.

-
-

Reserved words

Server function names cannot collide with instance method names from the current class or its parent classes.

-

The following words cannot be used in server functions:

-
    -
  • prepare
  • -
  • initiate
  • -
  • hydrate
  • -
  • update
  • -
  • terminate
  • -
-

Server functions named start will not generate an API endpoint and can only be called by other server functions.

-

Caveats

Automatically generated API endpoints are not meant to be used by 3rd-party apps.

-

The URL and implementation may change between versions of Nullstack.

-
-

✨ If you want to build an API, learn more about how to create an API with Nullstack.

-
-

Next step

⚔ Learn about the context.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/funcoes-de-servidor/index.json b/docs/pt-br/funcoes-de-servidor/index.json deleted file mode 100644 index 2eeec455..00000000 --- a/docs/pt-br/funcoes-de-servidor/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Server Functions","html":"

Server functions are specialized microservices that at transpile time are converted into API entry points.

\n

To flag a function as a server function, you must declare it as static async.

\n

Being a static function means it has no access to the instance scope.

\n

However, instead of calling the static version from the class, you must invoke it as an instance function.

\n

Server functions can be called anytime in your code and are not limited to prerender steps.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  static async increment(context) {\n    context.count++;\n  }\n\n  async handleClick() {\n    await this.increment();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

✨ Learn more about the server context.

\n
\n

Client behavior

When you call a server function from the client, the arguments will be serialized as JSON.

\n

The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.

\n

The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  static async increment(context) {\n    context.count++;\n    return context.count;\n  }\n\n  async handleClick() {\n    this.count = await this.increment();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Server behavior

Server functions will be used as local functions, simply aliasing the instance call to the class and merging the arguments with the server context.

\n

Date Convenience

Dates are serialized as UTC in JSON and deserialized back to Date objects.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  async initiate() {\n    const date = new Date();\n    const verified = this.verifyDay({date});\n  }\n\n  static async verifyDay({date}) {\n    return date.getDay() === new Date().getDay();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Fetch Convenience

fetch is available in both server and client functions for the sake of isomorphy.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    const url = 'https://api.github.com/repos/nullstack/nullstack/issues';\n    const response = await fetch(url);\n    this.issues = await response.json();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Server only imports

Imported dependencies that are only used inside server functions will be excluded from the client bundle.

\n

This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.

\n
import Nullstack from 'nullstack';\nimport {readFileSync} from 'fs';\nimport {Remarkable} from 'remarkable';\n\nclass Application extends Nullstack {\n\n  static async getTasks() {\n    const readme = readFileSync('README.md', 'utf-8');\n    return new Remarkable().render(readme);\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

Security

Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.

\n
\n

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

\n
\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  static async getCount({request, count}) {\n    if(!request.session.user) return 0;\n    return count;\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

💡 Server functions are not exposed to the client.

\n
\n
\n

✨ Learn more about the NJS file extension.

\n
\n

Reserved words

Server function names cannot collide with instance method names from the current class or its parent classes.

\n

The following words cannot be used in server functions:

\n
    \n
  • prepare
  • \n
  • initiate
  • \n
  • hydrate
  • \n
  • update
  • \n
  • terminate
  • \n
\n

Server functions named start will not generate an API endpoint and can only be called by other server functions.

\n

Caveats

Automatically generated API endpoints are not meant to be used by 3rd-party apps.

\n

The URL and implementation may change between versions of Nullstack.

\n
\n

✨ If you want to build an API, learn more about how to create an API with Nullstack.

\n
\n

Next step

⚔ Learn about the context.

\n","description":"Server functions are specialized microservices that at transpile time are converted into API entry points"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Server Functions - Nullstack","description":"Server functions are specialized microservices that at transpile time are converted into API entry points"}} \ No newline at end of file diff --git a/docs/pt-br/geracao-de-sites-estaticos.html b/docs/pt-br/geracao-de-sites-estaticos.html deleted file mode 100644 index a0b7441c..00000000 --- a/docs/pt-br/geracao-de-sites-estaticos.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - undefined - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Use Nullstack para gerar websites estáticos para aplicações estáticas ultrarrápidas usando todo o potencial do cliente Nullstack sem a necessidade de haver um back-end de node.js.

-

Websites estáticos são úteis para aplicações read-only como blogs e documentação

-
-

💡 Esta documentação é na verdade um site estático gerado com Nullstack

-
-

Todos os benefícios de renderização no lado do servidor se aplicam para websites gerados estáticamente.

-

Você pode gerar um website estático a partir da sua aplicação Nullstack com o seguinte comando npx:

-
npx create-nullstatic-app
-
-
-

🔥 Você deve estar em uma pasta de projeto Nullstack para executar esse comando.

-
-

Por padrão, a sua aplicação Nullstack será criada na pasta static.

-

Você pode mudar a pasta padrão por passá-la para o comando como um argumento:

-
npx create-nullstatic-app docs
-
-

O Nullstatic generator irá executar a sua aplicação no modo produção e irá rastrear cada link para uma rota interna que encontrar no seu DOM.

-
-

💡 Certifique-se que a porta de produção do servidor se encontra livre quando executar esse comando.

-
-

O manifest.json e o conteúdo da pasta pública serão copiados para a pasta de destino.

-

Além de gerar raw HTML também irá gerar um arquivo JSON para cada rota com uma cópia do estado.

-

Na primeira visita para a sua aplicação estática, HTML será veiculado e hidratado.

-

Nos pedidos subsequentes, Nullstack irá buscar o JSON gerado e atualizar o estado da aplicação sem que haja a necessidade de recarregar a página.

-

Isso, na verdade, oferece não apenas um site estático gerado, mas um API gerado estaticamente que alimenta a Single Page Application sem nenhum custo.

-

Boas Práticas

Você pode adicionar um script para a sua package.json a fim de gerar o seu website estático em uma pasta personalizada:

-
{
-  "name": "nullstack.github.io",
-  "version": "0.0.1",
-  "description": "",
-  "author": "",
-  "license": "ISC",
-  "devDependencies": {
-    "nullstack": "~0.9.0"
-  },
-  "scripts": {
-    "start": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=development --watch",
-    "build": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=production",
-    "ssg": "npx create-nullstatic-app docs"
-  }
-}
-
-
-

Ressalvas

Nullstatic rastreia a sua aplicação apenas até a resolução de initiate, outras solicitações de API acionadas por eventos serão ignoradas.

-

Nullstatic rastreará um URL "/404" e gerará um "/404.html" e um "/404/index.html".

-

Próximo passo

⚔ Aprenda mais sobre o trabalhador de serviço.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/geracao-de-sites-estaticos/index.html b/docs/pt-br/geracao-de-sites-estaticos/index.html deleted file mode 100644 index a0b7441c..00000000 --- a/docs/pt-br/geracao-de-sites-estaticos/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - undefined - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Use Nullstack para gerar websites estáticos para aplicações estáticas ultrarrápidas usando todo o potencial do cliente Nullstack sem a necessidade de haver um back-end de node.js.

-

Websites estáticos são úteis para aplicações read-only como blogs e documentação

-
-

💡 Esta documentação é na verdade um site estático gerado com Nullstack

-
-

Todos os benefícios de renderização no lado do servidor se aplicam para websites gerados estáticamente.

-

Você pode gerar um website estático a partir da sua aplicação Nullstack com o seguinte comando npx:

-
npx create-nullstatic-app
-
-
-

🔥 Você deve estar em uma pasta de projeto Nullstack para executar esse comando.

-
-

Por padrão, a sua aplicação Nullstack será criada na pasta static.

-

Você pode mudar a pasta padrão por passá-la para o comando como um argumento:

-
npx create-nullstatic-app docs
-
-

O Nullstatic generator irá executar a sua aplicação no modo produção e irá rastrear cada link para uma rota interna que encontrar no seu DOM.

-
-

💡 Certifique-se que a porta de produção do servidor se encontra livre quando executar esse comando.

-
-

O manifest.json e o conteúdo da pasta pública serão copiados para a pasta de destino.

-

Além de gerar raw HTML também irá gerar um arquivo JSON para cada rota com uma cópia do estado.

-

Na primeira visita para a sua aplicação estática, HTML será veiculado e hidratado.

-

Nos pedidos subsequentes, Nullstack irá buscar o JSON gerado e atualizar o estado da aplicação sem que haja a necessidade de recarregar a página.

-

Isso, na verdade, oferece não apenas um site estático gerado, mas um API gerado estaticamente que alimenta a Single Page Application sem nenhum custo.

-

Boas Práticas

Você pode adicionar um script para a sua package.json a fim de gerar o seu website estático em uma pasta personalizada:

-
{
-  "name": "nullstack.github.io",
-  "version": "0.0.1",
-  "description": "",
-  "author": "",
-  "license": "ISC",
-  "devDependencies": {
-    "nullstack": "~0.9.0"
-  },
-  "scripts": {
-    "start": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=development --watch",
-    "build": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=production",
-    "ssg": "npx create-nullstatic-app docs"
-  }
-}
-
-
-

Ressalvas

Nullstatic rastreia a sua aplicação apenas até a resolução de initiate, outras solicitações de API acionadas por eventos serão ignoradas.

-

Nullstatic rastreará um URL "/404" e gerará um "/404.html" e um "/404/index.html".

-

Próximo passo

⚔ Aprenda mais sobre o trabalhador de serviço.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/geracao-de-sites-estaticos/index.json b/docs/pt-br/geracao-de-sites-estaticos/index.json deleted file mode 100644 index 4a89eb94..00000000 --- a/docs/pt-br/geracao-de-sites-estaticos/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"","html":"

Use Nullstack para gerar websites estáticos para aplicações estáticas ultrarrápidas usando todo o potencial do cliente Nullstack sem a necessidade de haver um back-end de node.js.

\n

Websites estáticos são úteis para aplicações read-only como blogs e documentação

\n
\n

💡 Esta documentação é na verdade um site estático gerado com Nullstack

\n
\n

Todos os benefícios de renderização no lado do servidor se aplicam para websites gerados estáticamente.

\n

Você pode gerar um website estático a partir da sua aplicação Nullstack com o seguinte comando npx:

\n
npx create-nullstatic-app\n
\n
\n

🔥 Você deve estar em uma pasta de projeto Nullstack para executar esse comando.

\n
\n

Por padrão, a sua aplicação Nullstack será criada na pasta static.

\n

Você pode mudar a pasta padrão por passá-la para o comando como um argumento:

\n
npx create-nullstatic-app docs\n
\n

O Nullstatic generator irá executar a sua aplicação no modo produção e irá rastrear cada link para uma rota interna que encontrar no seu DOM.

\n
\n

💡 Certifique-se que a porta de produção do servidor se encontra livre quando executar esse comando.

\n
\n

O manifest.json e o conteúdo da pasta pública serão copiados para a pasta de destino.

\n

Além de gerar raw HTML também irá gerar um arquivo JSON para cada rota com uma cópia do estado.

\n

Na primeira visita para a sua aplicação estática, HTML será veiculado e hidratado.

\n

Nos pedidos subsequentes, Nullstack irá buscar o JSON gerado e atualizar o estado da aplicação sem que haja a necessidade de recarregar a página.

\n

Isso, na verdade, oferece não apenas um site estático gerado, mas um API gerado estaticamente que alimenta a Single Page Application sem nenhum custo.

\n

Boas Práticas

Você pode adicionar um script para a sua package.json a fim de gerar o seu website estático em uma pasta personalizada:

\n
{\n  \"name\": \"nullstack.github.io\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"nullstack\": \"~0.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"npx webpack --config node_modules/nullstack/webpack.config.js --mode=development --watch\",\n    \"build\": \"npx webpack --config node_modules/nullstack/webpack.config.js --mode=production\",\n    \"ssg\": \"npx create-nullstatic-app docs\"\n  }\n}\n\n
\n

Ressalvas

Nullstatic rastreia a sua aplicação apenas até a resolução de initiate, outras solicitações de API acionadas por eventos serão ignoradas.

\n

Nullstatic rastreará um URL "/404" e gerará um "/404.html" e um "/404/index.html".

\n

Próximo passo

⚔ Aprenda mais sobre o trabalhador de serviço.

\n","título":"Geração de Site Estático","descrição":"Use Nullstack para gerar websites estáticos para aplicações estáticas ultrarrápidas usando todo o potencial de Nullstack sem a necessidade de ter um back-end de node.js"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"undefined - Nullstack"}} \ No newline at end of file diff --git a/docs/pt-br/index.html b/docs/pt-br/index.html deleted file mode 100644 index af0b34af..00000000 --- a/docs/pt-br/index.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - Componentes Javascript Full-stack - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Componentes Javascript Full-stack

para exércitos de um dev só

Nullstack é um framework full-stack para construir aplicações web progressivas.

Ele conecta uma camada de UI com estado a microserviços especializados no mesmo componente usando vanilla javascript.

Concentre-se em resolver sua lógica de negócios em vez de escrever código para interoperabilidade.

Renderização no Servidor

Nullstack gera HTML otimizado e com SEO pronto para o primeiro rascunho de sua rota em uma única requisição usando funções locais e com zero dependências javascript no cliente.

Single Page Application

Após hidratação, requisições irão buscar JSON de uma API gerada automaticamente por funções do servidor, atualizar o estado da aplicação e renderizar a página novamente.

Geração de Site Estático

Você pode até usar o Nullstack para gerar sites estáticos ultra-rápidos que servem HTML e se tornam uma Single Page Application usando uma API estática gerada automaticamente.

Recursos Completos como Componentes

Nullstack não é apenas outra parte de sua stack, mas sim a sua stack

Sua aplicação pode ser exportado do back-end para o front-end como um componente e montado em outra aplicação

import Nullstack from 'nullstack';
-
-class ProductList extends Nullstack {
-
-  products = [];
-
-  static async getProducts({ database }) {
-    const [products] = await database.query(
-      'SELECT * FROM products'
-    );
-    return products;
-  }
-
-  async initiate() {
-    this.products = await this.getProducts();
-  }
-
-  static async deleteProduct({ database, id }) {
-    await database.query(
-      'DELETE FROM products WHERE id=?', 
-      [id]
-    );
-  }
-
-  async remove({ id }) {
-    await this.deleteProduct({ id });
-    await this.initiate();
-  }
-
-  renderProduct({ id, name }) {
-    return (
-      <li>
-        <button onclick={this.remove} id={id}>
-          {name}
-        </button>    
-      </li>
-    )
-  }
-  
-  render() {
-    return (
-      <ul>
-        {this.products.map((product) => (
-          <Product {...product} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default ProductList;
import Nullstack from 'nullstack';
-
-class ProductForm extends Nullstack {
-
-  name = '';
-  price = 0;
-
-  static async getProductById({ database, id }) {
-    const [products] = await database.query(
-      'SELECT * FROM products WHERE id=? LIMIT 1', 
-      [id]
-    );
-    return products[0];
-  }
-
-  async initiate({ params }) {
-    const product = await this.getProductById({
-      id: params.id
-    });
-    this.name = product.name;
-    this.price = product.price;
-  }
-
-  static async updateProduct({ database, name, price, id }) {
-    await database.query(
-      'UPDATE products SET name=?, price=? WHERE id=?',
-      [name, price, id]
-    );
-  }
-
-  async submit({ router, params }) {
-    await this.updateProduct({
-      id: params.id,
-      name: this.name,
-      price: this.price
-    });
-    router.url = '/products';
-  }
-  
-  render() {
-    return (
-      <form onsubmit={this.submit}>
-        <input class="form-control" bind={this.name} />
-        <input type="number" step=".01" bind={this.price} />
-        <button>Submit</button>
-      </form>
-    )
-  }
-
-}
-
-export default ProductForm;

O exemplo acima é o código completo de uma listagem de produtos e um formulário de edição sem esconder nenhuma linha.

Ambos os componentes invocam funções de servidor para ter acesso ao banco de dados MySQL no meio do JavaScript sem você ter que pensar em APIs.

A Produtividade está nos Detalhes

Os recursos do Nullstack foram extraídos de projetos da vida real com conveniência e consistência em mente

import Nullstack from 'nullstack';
-
-class Controlled extends Nullstack {
-
-  count = 0;
-
-  increment({delta}) {
-    this.count += delta;
-  }
-  
-  render() {
-    return (
-      <div>
-        <button onclick={this.increment} delta={-1}> 
-          {this.count}
-        </button>
-        <span> {this.count} </span>
-        <button onclick={this.increment} delta={1}> 
-          {this.count}
-        </button>
-      </div>
-    )
-  }
-
-}
-
-export default Controlled;
import Nullstack from 'nullstack';
-
-class Binding extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  
-  object = {number: 1};
-  array = ['a', 'b', 'c'];
-  
-  render({params}) {
-    return (
-      <form>
-        <input bind={this.number} />
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.number} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </form>
-    )
-  }
-
-}
-
-export default Binding;
import Nullstack from 'nullstack';
-
-class Routes extends Nullstack {
-
-  renderPost({params}) {
-    return (
-      <div>
-        <div route="/post/getting-started">
-          npx create-nullstack-app name
-        </div>
-        <div route="*"> {params.slug} </div>
-      </div>
-    )
-  }
-  
-  render() {
-    return (
-      <div> 
-        <Post route="/post/:slug" />
-        <a href="/post/hello-world"> Welcome </a>
-      </div>
-    )
-  }
-
-}
-
-export default Routes;
import Nullstack from 'nullstack';
-
-class Lifecycle extends Nullstack {
-  
-  prepare({environment}) {
-    const {server, client} = environment;
-  }
-
-  async initiate({environment}) {
-    const {server, client} = environment;
-  }
-
-  async hydrate({environment}) {
-    const {client} = environment;
-  }
-
-  async update({environment}) {
-    const {client} = environment;
-  }
-
-  async terminate({environment}) {
-    const {client} = environment;
-  }
-
-}
-
-export default Lifecycle;

Assista aos nossos vídeos tutoriais do Nullstack

Nullstack se preocupa em tornar seu conteúdo o mais direto ao ponto e fácil de entender quanto possível

Full-stack com Nullstack - Parte 1
Full-stack com Nullstack - Parte 2
Full-stack com Nullstack - Parte 3

Por que você deve usar o Nullstack?

Desenvolvimento Escalável

Cada projeto começa pequeno e se torna complexo com o tempo. Escale conforme avança, não importa o tamanho da equipe.

Sem compromissos, sem imposições.

Desenvolvimento Orientado a Recursos

Desenvolvimento de back e front end de um recurso no mesmo componente de forma organizada com facilidade de visão geral.

Verdadeira componentização e reutilização de código.

Ecossistema já existente

Tira proveito de todo e qualquer pacote isomórfico em Vanilla Javascript já feito em toda história.

Todo o sua aplicação fala a mesma língua.

Adapte-se rapidamente às mudanças de escopo

A estrutura horizontal, ao contrário de uma hierárquica, torna muito mais fácil mover os recursos.

Flexibilidade acima de burocracia.
Começar! ╰(*°▽°*)╯
- - - \ No newline at end of file diff --git a/docs/pt-br/index.json b/docs/pt-br/index.json deleted file mode 100644 index a196b317..00000000 --- a/docs/pt-br/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-2":{"locale":"pt-BR","i18n":{"title":"Componentes Javascript Full-stack","description":"Nullstack é um framework javascript full-stack para construir aplicações web progressivas","hero":{"heading":"Componentes Javascript Full-stack","tagline":"para exércitos de um dev só","descriptions":["Nullstack é um framework full-stack para construir aplicações web progressivas.","Ele conecta uma camada de UI com estado a microserviços especializados no mesmo componente usando vanilla javascript.","Concentre-se em resolver sua lógica de negócios em vez de escrever código para interoperabilidade."]},"cycle":{"ssr":{"title":"Renderização no Servidor","link":"/pt-br/renderizando-no-servidor","text":"Nullstack gera HTML otimizado e com SEO pronto para o primeiro rascunho de sua rota em uma única requisição usando funções locais e com zero dependências javascript no cliente."},"spa":{"title":"Single Page Application","link":"/pt-br/ciclo-de-vida-full-stack","text":"Após hidratação, requisições irão buscar JSON de uma API gerada automaticamente por funções do servidor, atualizar o estado da aplicação e renderizar a página novamente."},"ssg":{"title":"Geração de Site Estático","link":"/pt-br/geracao-de-sites-estaticos","text":"Você pode até usar o Nullstack para gerar sites estáticos ultra-rápidos que servem HTML e se tornam uma Single Page Application usando uma API estática gerada automaticamente."}},"about":{"heading":"Recursos Completos como Componentes","taglines":["Nullstack não é apenas outra parte de sua stack, mas sim a sua stack","Sua aplicação pode ser exportado do back-end para o front-end como um componente e montado em outra aplicação"]},"showcase":{"descriptions":["O exemplo acima é o código completo de uma listagem de produtos e um formulário de edição sem esconder nenhuma linha.","Ambos os componentes invocam funções de servidor para ter acesso ao banco de dados MySQL no meio do JavaScript sem você ter que pensar em APIs."]},"productivity":{"heading":"A Produtividade está nos Detalhes","tagline":"Os recursos do Nullstack foram extraídos de projetos da vida real com conveniência e consistência em mente"},"features":[{"title":"Componentes com Estado","key":"Stateful","link":"/pt-br/componentes-com-estado"},{"title":"Vínculo Bidirecional","key":"Binding","link":"/pt-br/vinculo-bidirecional"},{"title":"Rotas Integradas","key":"Routes","link":"/pt-br/rotas-e-parametros"},{"title":"Ciclo de Vida Full-stack","key":"Lifecycle","link":"/pt-br/ciclo-de-vida-full-stack"}],"playlist":{"heading":"Assista aos nossos vídeos tutoriais do Nullstack","tagline":"Nullstack se preocupa em tornar seu conteúdo o mais direto ao ponto e fácil de entender quanto possível","videos":[{"title":"Full-stack com Nullstack - Parte 1","link":"https://www.youtube.com/watch?v=ieLVXZGXUkI&list=PL5ylYELQy1hz1tcnZcP44xRxETpH9bTUe","thumbnail":"/thumbnail-pt-br-1.webp"},{"title":"Full-stack com Nullstack - Parte 2","link":"https://www.youtube.com/watch?v=BHrNgi2UZ6Q&list=PL5ylYELQy1hz1tcnZcP44xRxETpH9bTUe","thumbnail":"/thumbnail-pt-br-2.webp"},{"title":"Full-stack com Nullstack - Parte 3","link":"https://www.youtube.com/watch?v=uRlvILvJ0Oc&list=PL5ylYELQy1hz1tcnZcP44xRxETpH9bTUe","thumbnail":"/thumbnail-pt-br-3.webp"}]},"why":{"heading":"Por que você deve usar o Nullstack?","reasons":[{"title":"Desenvolvimento Escalável","description":"Cada projeto começa pequeno e se torna complexo com o tempo. Escale conforme avança, não importa o tamanho da equipe.","link":"/pt-br/sobre","closer":"Sem compromissos, sem imposições."},{"title":"Desenvolvimento Orientado a Recursos","description":"Desenvolvimento de back e front end de um recurso no mesmo componente de forma organizada com facilidade de visão geral.","link":"/pt-br/sobre#feature-driven","closer":"Verdadeira componentização e reutilização de código."},{"title":"Ecossistema já existente","description":"Tira proveito de todo e qualquer pacote isomórfico em Vanilla Javascript já feito em toda história.","link":"/pt-br/sobre#tudo---possivel","closer":"Todo o sua aplicação fala a mesma língua."},{"title":"Adapte-se rapidamente às mudanças de escopo","description":"A estrutura horizontal, ao contrário de uma hierárquica, torna muito mais fácil mover os recursos.","link":"/pt-br/sobre#por-que-inje--o-de-depend-ncia-em-vez-de-modularidade","closer":"Flexibilidade acima de burocracia."}],"getStarted":{"text":"Começar!","link":"/pt-br/comecando"}}}},"n-0-0-2-0-1-0-0-0-0-0":{},"n-0-0-2-0-1-0-1-0-0-0":{},"n-0-0-2-0-1-0-2-0-0-0":{},"ProductList":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass ProductList extends Nullstack {\r\n\r\n products = [];\r\n\r\n static async getProducts({ database }) {\r\n const [products] = await database.query(\r\n 'SELECT * FROM products'\r\n );\r\n return products;\r\n }\r\n\r\n async initiate() {\r\n this.products = await this.getProducts();\r\n }\r\n\r\n static async deleteProduct({ database, id }) {\r\n await database.query(\r\n 'DELETE FROM products WHERE id=?', \r\n [id]\r\n );\r\n }\r\n\r\n async remove({ id }) {\r\n await this.deleteProduct({ id });\r\n await this.initiate();\r\n }\r\n\r\n renderProduct({ id, name }) {\r\n return (\r\n <li>\r\n <button onclick={this.remove} id={id}>\r\n {name}\r\n </button> \r\n </li>\r\n )\r\n }\r\n \r\n render() {\r\n return (\r\n <ul>\r\n {this.products.map((product) => (\r\n <Product {...product} />\r\n ))}\r\n </ul>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default ProductList;"},"ProductForm":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass ProductForm extends Nullstack {\r\n\r\n name = '';\r\n price = 0;\r\n\r\n static async getProductById({ database, id }) {\r\n const [products] = await database.query(\r\n 'SELECT * FROM products WHERE id=? LIMIT 1', \r\n [id]\r\n );\r\n return products[0];\r\n }\r\n\r\n async initiate({ params }) {\r\n const product = await this.getProductById({\r\n id: params.id\r\n });\r\n this.name = product.name;\r\n this.price = product.price;\r\n }\r\n\r\n static async updateProduct({ database, name, price, id }) {\r\n await database.query(\r\n 'UPDATE products SET name=?, price=? WHERE id=?',\r\n [name, price, id]\r\n );\r\n }\r\n\r\n async submit({ router, params }) {\r\n await this.updateProduct({\r\n id: params.id,\r\n name: this.name,\r\n price: this.price\r\n });\r\n router.url = '/products';\r\n }\r\n \r\n render() {\r\n return (\r\n <form onsubmit={this.submit}>\r\n <input class=\"form-control\" bind={this.name} />\r\n <input type=\"number\" step=\".01\" bind={this.price} />\r\n <button>Submit</button>\r\n </form>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default ProductForm;"},"Stateful":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Controlled extends Nullstack {\r\n\r\n count = 0;\r\n\r\n increment({delta}) {\r\n this.count += delta;\r\n }\r\n \r\n render() {\r\n return (\r\n <div>\r\n <button onclick={this.increment} delta={-1}> \r\n {this.count}\r\n </button>\r\n <span> {this.count} </span>\r\n <button onclick={this.increment} delta={1}> \r\n {this.count}\r\n </button>\r\n </div>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default Controlled;"},"Binding":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Binding extends Nullstack {\r\n\r\n number = 1;\r\n boolean = true;\r\n \r\n object = {number: 1};\r\n array = ['a', 'b', 'c'];\r\n \r\n render({params}) {\r\n return (\r\n <form>\r\n <input bind={this.number} />\r\n <input bind={this.boolean} type=\"checkbox\" />\r\n <input bind={this.object.number} />\r\n {this.array.map((value, index) => (\r\n <input bind={this.array[index]} />\r\n ))}\r\n <input bind={params.page} />\r\n </form>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default Binding;"},"Routes":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Routes extends Nullstack {\r\n\r\n renderPost({params}) {\r\n return (\r\n <div>\r\n <div route=\"/post/getting-started\">\r\n npx create-nullstack-app name\r\n </div>\r\n <div route=\"*\"> {params.slug} </div>\r\n </div>\r\n )\r\n }\r\n \r\n render() {\r\n return (\r\n <div> \r\n <Post route=\"/post/:slug\" />\r\n <a href=\"/post/hello-world\"> Welcome </a>\r\n </div>\r\n )\r\n }\r\n\r\n}\r\n\r\nexport default Routes;"},"Lifecycle":{"html":"import Nullstack from 'nullstack';\r\n\r\nclass Lifecycle extends Nullstack {\r\n \r\n prepare({environment}) {\r\n const {server, client} = environment;\r\n }\r\n\r\n async initiate({environment}) {\r\n const {server, client} = environment;\r\n }\r\n\r\n async hydrate({environment}) {\r\n const {client} = environment;\r\n }\r\n\r\n async update({environment}) {\r\n const {client} = environment;\r\n }\r\n\r\n async terminate({environment}) {\r\n const {client} = environment;\r\n }\r\n\r\n}\r\n\r\nexport default Lifecycle;"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"priority":1,"title":"Componentes Javascript Full-stack - Nullstack","description":"Nullstack é um framework javascript full-stack para construir aplicações web progressivas","locale":"pt-BR"}} \ No newline at end of file diff --git a/docs/pt-br/inicializacao-da-aplicacao.html b/docs/pt-br/inicializacao-da-aplicacao.html deleted file mode 100644 index 9eab6499..00000000 --- a/docs/pt-br/inicializacao-da-aplicacao.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - Inicialização da Aplicação - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Inicialização da Aplicação

O arquivo index.js na raiz da aplicação é responsável por iniciar a aplicação.

-

Quando você executa a aplicação com npm start ou node .production/server.js, o index chama a função start em seu src/Application.js.

-

A função start será executada apenas uma vez quando sua aplicação for inicializada e é um bom lugar para configurar seu contexto de servidor.

-
import Nullstack from 'nullstack';
-import database from './database';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.database = database;
-  }
-
-}
-
-export default Application;
-
-

Padrão de inicialização de dependência

Um bom padrão para trabalhar com dependências que requerem configurações em tempo de inicialização é definir uma função start na dependência e chamá-la na função start da aplicação passando o contexto do servidor.

-
import Nullstack from 'nullstack';
-import Dependency from './Dependency';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    Dependency.start(context);
-  }
-
-}
-
-export default Application;
-
-
-

🔒 As funções de servidor com o nome começando com "start" (e opcionalmente seguido por uma letra maiúscula) não geram um endpoint de API para evitar inundação de contexto malicioso.

-
-

Next step

⚔ Aprenda sobre a chave data do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/inicializacao-da-aplicacao/index.html b/docs/pt-br/inicializacao-da-aplicacao/index.html deleted file mode 100644 index 9eab6499..00000000 --- a/docs/pt-br/inicializacao-da-aplicacao/index.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - Inicialização da Aplicação - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Inicialização da Aplicação

O arquivo index.js na raiz da aplicação é responsável por iniciar a aplicação.

-

Quando você executa a aplicação com npm start ou node .production/server.js, o index chama a função start em seu src/Application.js.

-

A função start será executada apenas uma vez quando sua aplicação for inicializada e é um bom lugar para configurar seu contexto de servidor.

-
import Nullstack from 'nullstack';
-import database from './database';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    context.database = database;
-  }
-
-}
-
-export default Application;
-
-

Padrão de inicialização de dependência

Um bom padrão para trabalhar com dependências que requerem configurações em tempo de inicialização é definir uma função start na dependência e chamá-la na função start da aplicação passando o contexto do servidor.

-
import Nullstack from 'nullstack';
-import Dependency from './Dependency';
-
-class Application extends Nullstack {
-
-  static async start(context) {
-    Dependency.start(context);
-  }
-
-}
-
-export default Application;
-
-
-

🔒 As funções de servidor com o nome começando com "start" (e opcionalmente seguido por uma letra maiúscula) não geram um endpoint de API para evitar inundação de contexto malicioso.

-
-

Next step

⚔ Aprenda sobre a chave data do contexto.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/inicializacao-da-aplicacao/index.json b/docs/pt-br/inicializacao-da-aplicacao/index.json deleted file mode 100644 index 3789c1ff..00000000 --- a/docs/pt-br/inicializacao-da-aplicacao/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Inicialização da Aplicação","html":"

O arquivo index.js na raiz da aplicação é responsável por iniciar a aplicação.

\n

Quando você executa a aplicação com npm start ou node .production/server.js, o index chama a função start em seu src/Application.js.

\n

A função start será executada apenas uma vez quando sua aplicação for inicializada e é um bom lugar para configurar seu contexto de servidor.

\n
import Nullstack from 'nullstack';\nimport database from './database';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    context.database = database;\n  }\n\n}\n\nexport default Application;\n
\n

Padrão de inicialização de dependência

Um bom padrão para trabalhar com dependências que requerem configurações em tempo de inicialização é definir uma função start na dependência e chamá-la na função start da aplicação passando o contexto do servidor.

\n
import Nullstack from 'nullstack';\nimport Dependency from './Dependency';\n\nclass Application extends Nullstack {\n\n  static async start(context) {\n    Dependency.start(context);\n  }\n\n}\n\nexport default Application;\n
\n
\n

🔒 As funções de servidor com o nome começando com "start" (e opcionalmente seguido por uma letra maiúscula) não geram um endpoint de API para evitar inundação de contexto malicioso.

\n
\n

Next step

⚔ Aprenda sobre a chave data do contexto.

\n","description":"A função de inicialização será executada apenas uma vez quando sua aplicação for inicializada e é um bom lugar para configurar o contexto do seu servidor"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Inicialização da Aplicação - Nullstack","description":"A função de inicialização será executada apenas uma vez quando sua aplicação for inicializada e é um bom lugar para configurar o contexto do seu servidor"}} \ No newline at end of file diff --git a/docs/pt-br/instancia-self.html b/docs/pt-br/instancia-self.html deleted file mode 100644 index 4407424a..00000000 --- a/docs/pt-br/instancia-self.html +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - self da Instância - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

self da Instância

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client
  • -
-

Ele te dá informações sobre o ciclo de vida da instância e sua key única.

-

Cada instância recebe seu própio objeto self.

-

As seguintes keys estão disponíveis no objeto:

-
    -
  • initiated: boolean
  • -
  • hydrated: boolean
  • -
  • prerendered: boolean
  • -
  • element: HTMLElement
  • -
  • key: string
  • -
-

Quando um método do ciclo de vida é resolvido, mesmo que não declarado, uma chave equivalente é setada para true no self.

-

Se o componente tiver sido renderizado no lado do servidor a chave prerendered continuará como true até que seja finalizado.

-

A chave element aponta para o seletor na DOM e sua existência só é garantida quando o hydrate está sendo chamado, pois prepare e initiate podem estar rodando no servidor.

-
-

💡 Não use a chave element para adivinhar o ambiente, ao invés use environment para isso.

-
-

Observar o self é um bom jeito de evitar dar informações irrelevantes para o usuário final

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.price = await this.getPrice();
-  }
-
-  async hydrate({self}) {
-    self.element.querySelector('input').focus();
-  }
- 
-  render({self}) {
-    if(!self.prerendered && !self.initiated) return false;
-    return (
-      <form> 
-        <input type="number" bind={this.price} />
-        <button disabled={!self.hydrated}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-
-

💡 Componentes que estão otimizados em functional components não tem acesso ao self.

-
-

key da Instância

    -
  • Tipo: string
  • -
  • Origem: Contexto Componente
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client ou depois de definido seu valor como atributo
  • -
-

Ele permite que você persista a instância quando é movida no DOM.

-

Você pode declarar uma key por instância.

-
-

💡 Se você não declarar a key o nullstack irá gerar uma baseada na profundidade da dom.

-
-
-

🔥 As keys não podem começar com "_." para evitar conflito com as keys geradas pelo Nullstack

-
-

As keys devem ser globalmente únicas já que o componente poderá ser movido para qualquer lugar da DOM e não apenas entre os componentes irmãos.

-

Preservando o estado

As keys são úteis para preservar o estado em componentes com estado quando você os move para dentro da DOM.

-

Isto é especialmente útil para listas com tamanho dinâmico que invocam os componentes.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Instâncias compartilhadas

Você também pode usar as keys para compartilhar a instância entre dois elementos.

-

Apenas o primeiro encontro da key irá executar o lifecycle.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

key da Instância

    -
  • Tipo: string
  • -
  • Origem: Contexto Componente
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client ou depois de definido seu valor como atributo
  • -
-

Ele permite que você persista a instância quando é movida no DOM.

-

Você pode declarar uma key por instância.

-
-

💡 Se você não declarar a key o nullstack irá gerar uma baseada na profundidade da dom

-
-
-

🔥 As keys não podem começar com "_." para evitar conflito com as keys geradas pelo Nullstack

-
-

As keys devem ser globalmente únicas já que o componente poderá ser movido para qualquer lugar da DOM e não apenas entre os componentes irmãos.

-

Preservando o estado

As keys são úteis para preservar o estado em componentes com estado quando você os move para dentro da DOM.

-

Isto é especialmente útil para listas com tamanho dinâmico que invocam os componentes.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Instâncias compartilhadas

Você também pode usar as keys para compartilhar a instância entre dois elementos.

-

Apenas o primeiro encontro da key irá executar o lifecycle

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Próximo passo

⚔ Aprenda sobre requisicao e resposta do servidor.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/instancia-self/index.html b/docs/pt-br/instancia-self/index.html deleted file mode 100644 index 4407424a..00000000 --- a/docs/pt-br/instancia-self/index.html +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - self da Instância - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

self da Instância

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client
  • -
-

Ele te dá informações sobre o ciclo de vida da instância e sua key única.

-

Cada instância recebe seu própio objeto self.

-

As seguintes keys estão disponíveis no objeto:

-
    -
  • initiated: boolean
  • -
  • hydrated: boolean
  • -
  • prerendered: boolean
  • -
  • element: HTMLElement
  • -
  • key: string
  • -
-

Quando um método do ciclo de vida é resolvido, mesmo que não declarado, uma chave equivalente é setada para true no self.

-

Se o componente tiver sido renderizado no lado do servidor a chave prerendered continuará como true até que seja finalizado.

-

A chave element aponta para o seletor na DOM e sua existência só é garantida quando o hydrate está sendo chamado, pois prepare e initiate podem estar rodando no servidor.

-
-

💡 Não use a chave element para adivinhar o ambiente, ao invés use environment para isso.

-
-

Observar o self é um bom jeito de evitar dar informações irrelevantes para o usuário final

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.price = await this.getPrice();
-  }
-
-  async hydrate({self}) {
-    self.element.querySelector('input').focus();
-  }
- 
-  render({self}) {
-    if(!self.prerendered && !self.initiated) return false;
-    return (
-      <form> 
-        <input type="number" bind={this.price} />
-        <button disabled={!self.hydrated}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-
-

💡 Componentes que estão otimizados em functional components não tem acesso ao self.

-
-

key da Instância

    -
  • Tipo: string
  • -
  • Origem: Contexto Componente
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client ou depois de definido seu valor como atributo
  • -
-

Ele permite que você persista a instância quando é movida no DOM.

-

Você pode declarar uma key por instância.

-
-

💡 Se você não declarar a key o nullstack irá gerar uma baseada na profundidade da dom.

-
-
-

🔥 As keys não podem começar com "_." para evitar conflito com as keys geradas pelo Nullstack

-
-

As keys devem ser globalmente únicas já que o componente poderá ser movido para qualquer lugar da DOM e não apenas entre os componentes irmãos.

-

Preservando o estado

As keys são úteis para preservar o estado em componentes com estado quando você os move para dentro da DOM.

-

Isto é especialmente útil para listas com tamanho dinâmico que invocam os componentes.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Instâncias compartilhadas

Você também pode usar as keys para compartilhar a instância entre dois elementos.

-

Apenas o primeiro encontro da key irá executar o lifecycle.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

key da Instância

    -
  • Tipo: string
  • -
  • Origem: Contexto Componente
  • -
  • Disponibilidade: client
  • -
  • readonly no contexto do client ou depois de definido seu valor como atributo
  • -
-

Ele permite que você persista a instância quando é movida no DOM.

-

Você pode declarar uma key por instância.

-
-

💡 Se você não declarar a key o nullstack irá gerar uma baseada na profundidade da dom

-
-
-

🔥 As keys não podem começar com "_." para evitar conflito com as keys geradas pelo Nullstack

-
-

As keys devem ser globalmente únicas já que o componente poderá ser movido para qualquer lugar da DOM e não apenas entre os componentes irmãos.

-

Preservando o estado

As keys são úteis para preservar o estado em componentes com estado quando você os move para dentro da DOM.

-

Isto é especialmente útil para listas com tamanho dinâmico que invocam os componentes.

-
import Nullstack from 'nullstack';
-import Item from './Item';
-
-class List extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    this.items = await this.getItems();
-  }
- 
-  render({self}) {
-    const componentKey = self.key;
-    return (
-      <ul> 
-        {this.items.map((item) => (
-          <Item key={`${componentKey}-${item.id}`} {...item} />
-        ))}
-      </ul>
-    )
-  }
-
-}
-
-export default Page;
-
-

Instâncias compartilhadas

Você também pode usar as keys para compartilhar a instância entre dois elementos.

-

Apenas o primeiro encontro da key irá executar o lifecycle

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  render({amount}) {
-    return (
-      <div>
-        <button onclick={{count: this.count+1}}>
-          {this.count} x {amount} = {this.count * amount}
-        </button>  
-      </div>
-    )
-  }
-
-}
-
-export default Counter;
-
-
import Nullstack from 'nullstack';
-import Counter from './Counter';
-
-class Application extends Nullstack {
-
-  render() {
-    return (
-      <main>
-        <Counter key="a" amount={1} />
-        <Counter key="b" amount={2} />
-        <Counter key="b" amount={3} />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Próximo passo

⚔ Aprenda sobre requisicao e resposta do servidor.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/instancia-self/index.json b/docs/pt-br/instancia-self/index.json deleted file mode 100644 index c52fe99b..00000000 --- a/docs/pt-br/instancia-self/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"self da Instância","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: client
  • \n
  • readonly no contexto do client
  • \n
\n

Ele te dá informações sobre o ciclo de vida da instância e sua key única.

\n

Cada instância recebe seu própio objeto self.

\n

As seguintes keys estão disponíveis no objeto:

\n
    \n
  • initiated: boolean
  • \n
  • hydrated: boolean
  • \n
  • prerendered: boolean
  • \n
  • element: HTMLElement
  • \n
  • key: string
  • \n
\n

Quando um método do ciclo de vida é resolvido, mesmo que não declarado, uma chave equivalente é setada para true no self.

\n

Se o componente tiver sido renderizado no lado do servidor a chave prerendered continuará como true até que seja finalizado.

\n

A chave element aponta para o seletor na DOM e sua existência só é garantida quando o hydrate está sendo chamado, pois prepare e initiate podem estar rodando no servidor.

\n
\n

💡 Não use a chave element para adivinhar o ambiente, ao invés use environment para isso.

\n
\n

Observar o self é um bom jeito de evitar dar informações irrelevantes para o usuário final

\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.price = await this.getPrice();\n  }\n\n  async hydrate({self}) {\n    self.element.querySelector('input').focus();\n  }\n \n  render({self}) {\n    if(!self.prerendered && !self.initiated) return false;\n    return (\n      <form> \n        <input type=\"number\" bind={this.price} />\n        <button disabled={!self.hydrated}> \n          Save\n        </button>\n      </form>\n    )\n  }\n\n}\n\nexport default Page;\n
\n
\n

💡 Componentes que estão otimizados em functional components não tem acesso ao self.

\n
\n

key da Instância

    \n
  • Tipo: string
  • \n
  • Origem: Contexto Componente
  • \n
  • Disponibilidade: client
  • \n
  • readonly no contexto do client ou depois de definido seu valor como atributo
  • \n
\n

Ele permite que você persista a instância quando é movida no DOM.

\n

Você pode declarar uma key por instância.

\n
\n

💡 Se você não declarar a key o nullstack irá gerar uma baseada na profundidade da dom.

\n
\n
\n

🔥 As keys não podem começar com "_." para evitar conflito com as keys geradas pelo Nullstack

\n
\n

As keys devem ser globalmente únicas já que o componente poderá ser movido para qualquer lugar da DOM e não apenas entre os componentes irmãos.

\n

Preservando o estado

As keys são úteis para preservar o estado em componentes com estado quando você os move para dentro da DOM.

\n

Isto é especialmente útil para listas com tamanho dinâmico que invocam os componentes.

\n
import Nullstack from 'nullstack';\nimport Item from './Item';\n\nclass List extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.items = await this.getItems();\n  }\n \n  render({self}) {\n    const componentKey = self.key;\n    return (\n      <ul> \n        {this.items.map((item) => (\n          <Item key={`${componentKey}-${item.id}`} {...item} />\n        ))}\n      </ul>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Instâncias compartilhadas

Você também pode usar as keys para compartilhar a instância entre dois elementos.

\n

Apenas o primeiro encontro da key irá executar o lifecycle.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  render({amount}) {\n    return (\n      <div>\n        <button onclick={{count: this.count+1}}>\n          {this.count} x {amount} = {this.count * amount}\n        </button>  \n      </div>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  render() {\n    return (\n      <main>\n        <Counter key=\"a\" amount={1} />\n        <Counter key=\"b\" amount={2} />\n        <Counter key=\"b\" amount={3} />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

key da Instância

    \n
  • Tipo: string
  • \n
  • Origem: Contexto Componente
  • \n
  • Disponibilidade: client
  • \n
  • readonly no contexto do client ou depois de definido seu valor como atributo
  • \n
\n

Ele permite que você persista a instância quando é movida no DOM.

\n

Você pode declarar uma key por instância.

\n
\n

💡 Se você não declarar a key o nullstack irá gerar uma baseada na profundidade da dom

\n
\n
\n

🔥 As keys não podem começar com "_." para evitar conflito com as keys geradas pelo Nullstack

\n
\n

As keys devem ser globalmente únicas já que o componente poderá ser movido para qualquer lugar da DOM e não apenas entre os componentes irmãos.

\n

Preservando o estado

As keys são úteis para preservar o estado em componentes com estado quando você os move para dentro da DOM.

\n

Isto é especialmente útil para listas com tamanho dinâmico que invocam os componentes.

\n
import Nullstack from 'nullstack';\nimport Item from './Item';\n\nclass List extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    this.items = await this.getItems();\n  }\n \n  render({self}) {\n    const componentKey = self.key;\n    return (\n      <ul> \n        {this.items.map((item) => (\n          <Item key={`${componentKey}-${item.id}`} {...item} />\n        ))}\n      </ul>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Instâncias compartilhadas

Você também pode usar as keys para compartilhar a instância entre dois elementos.

\n

Apenas o primeiro encontro da key irá executar o lifecycle

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  render({amount}) {\n    return (\n      <div>\n        <button onclick={{count: this.count+1}}>\n          {this.count} x {amount} = {this.count * amount}\n        </button>  \n      </div>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
import Nullstack from 'nullstack';\nimport Counter from './Counter';\n\nclass Application extends Nullstack {\n\n  render() {\n    return (\n      <main>\n        <Counter key=\"a\" amount={1} />\n        <Counter key=\"b\" amount={2} />\n        <Counter key=\"b\" amount={3} />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Próximo passo

⚔ Aprenda sobre requisicao e resposta do servidor.

\n","description":"O objeto self é um proxy no Contexto Nullstack disponível no client e te dá informações sobre o ciclo de vida da instância"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"self da Instância - Nullstack","description":"O objeto self é um proxy no Contexto Nullstack disponível no client e te dá informações sobre o ciclo de vida da instância"}} \ No newline at end of file diff --git a/docs/pt-br/renderizacao-no-servidor.html b/docs/pt-br/renderizacao-no-servidor.html deleted file mode 100644 index c1ec51aa..00000000 --- a/docs/pt-br/renderizacao-no-servidor.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Página Não Encontrada - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Página Não Encontrada

- - - \ No newline at end of file diff --git a/docs/pt-br/renderizacao-no-servidor/index.html b/docs/pt-br/renderizacao-no-servidor/index.html deleted file mode 100644 index c1ec51aa..00000000 --- a/docs/pt-br/renderizacao-no-servidor/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Página Não Encontrada - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Página Não Encontrada

- - - \ No newline at end of file diff --git a/docs/pt-br/renderizacao-no-servidor/index.json b/docs/pt-br/renderizacao-no-servidor/index.json deleted file mode 100644 index b918fadd..00000000 --- a/docs/pt-br/renderizacao-no-servidor/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Página Não Encontrada","html":"

Talvez você queira aprender como criar uma pagina 404 com Nullstack?

\n

Se você está procurando por outra coisa, você deveria ler a documentação.

\n","description":"Desculpe, essa não é a página que você está procurando","status":404},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":404,"title":"Página Não Encontrada - Nullstack","description":"Desculpe, essa não é a página que você está procurando"}} \ No newline at end of file diff --git a/docs/pt-br/renderizando-no-servidor.html b/docs/pt-br/renderizando-no-servidor.html deleted file mode 100644 index 25eb6cc1..00000000 --- a/docs/pt-br/renderizando-no-servidor.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - Server-Side Rendering - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server-Side Rendering

Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from.

-

Server-side rendering is good for SEO since it gives as fast as possible crawlable markup for search engines.

-

Nullstack starts the application for the user by first serving HTML of only the requested page with no overhead.

-

Before serving the HTML, Nullstack will wait for prepare and initiate of all components of that route to be resolved.

-

While server-side rendering all server functions run locally without the need to fetch an API, making the process even faster.

-

After the document is already painted in the browser, Nullstack loads the javascript client bundle and starts the hydration process.

-

No further requests to the server are made to recover the application state during hydration.

-

The page head will generate the necessary meta tags for SEO based on the contents of the project and page context keys.

-

Next step

⚔ Learn about static site generation.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/renderizando-no-servidor/index.html b/docs/pt-br/renderizando-no-servidor/index.html deleted file mode 100644 index 25eb6cc1..00000000 --- a/docs/pt-br/renderizando-no-servidor/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - Server-Side Rendering - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server-Side Rendering

Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from.

-

Server-side rendering is good for SEO since it gives as fast as possible crawlable markup for search engines.

-

Nullstack starts the application for the user by first serving HTML of only the requested page with no overhead.

-

Before serving the HTML, Nullstack will wait for prepare and initiate of all components of that route to be resolved.

-

While server-side rendering all server functions run locally without the need to fetch an API, making the process even faster.

-

After the document is already painted in the browser, Nullstack loads the javascript client bundle and starts the hydration process.

-

No further requests to the server are made to recover the application state during hydration.

-

The page head will generate the necessary meta tags for SEO based on the contents of the project and page context keys.

-

Next step

⚔ Learn about static site generation.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/renderizando-no-servidor/index.json b/docs/pt-br/renderizando-no-servidor/index.json deleted file mode 100644 index 64173f32..00000000 --- a/docs/pt-br/renderizando-no-servidor/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Server-Side Rendering","html":"

Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from.

\n

Server-side rendering is good for SEO since it gives as fast as possible crawlable markup for search engines.

\n

Nullstack starts the application for the user by first serving HTML of only the requested page with no overhead.

\n

Before serving the HTML, Nullstack will wait for prepare and initiate of all components of that route to be resolved.

\n

While server-side rendering all server functions run locally without the need to fetch an API, making the process even faster.

\n

After the document is already painted in the browser, Nullstack loads the javascript client bundle and starts the hydration process.

\n

No further requests to the server are made to recover the application state during hydration.

\n

The page head will generate the necessary meta tags for SEO based on the contents of the project and page context keys.

\n

Next step

⚔ Learn about static site generation.

\n","description":"Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Server-Side Rendering - Nullstack","description":"Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from"}} \ No newline at end of file diff --git a/docs/pt-br/requisicao-e-resposta-do-servidor.html b/docs/pt-br/requisicao-e-resposta-do-servidor.html deleted file mode 100644 index 34a63393..00000000 --- a/docs/pt-br/requisicao-e-resposta-do-servidor.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - Requisição e resposta do servidor - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Requisição e resposta do servidor

A key do servidor

A key do servidor é um proxy em volta de uma instância do Express que roda por baixo dos panos.

-

O objeto do servidor está presenta apenas no contexto do servidor.

-

As seguintes funções são redirecionadas para o servidor Express:

-
    -
  • get
  • -
  • post
  • -
  • put
  • -
  • patch
  • -
  • delete
  • -
  • options
  • -
  • head
  • -
  • use
  • -
-
-

✨ Se você quer aprender como fazer uma API com Nullstack, este é o caminho.

-
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.get('/api/books', (request, response) => {
-      response.json({books: []});
-    });
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Outras keys disponíveis são:

-
    -
  • port: integer
  • -
  • maximumPayloadSize: string
  • -
  • cors: object
  • -
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.port = 3000;
-    server.maximumPayloadSize = '5mb';
-    server.cors = {
-      origin: 'http://localhost:6969',
-      optionsSuccessStatus: 200
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

O objeto cors será passado como argumento para o plugin do cors no express.

-

Requisição e resposta

Todo contexto de função do servidor é mesclado com os objetos request e response originais do Express.

-

Se você der uma resposta manualmente ela irá sobrescrever a response server-side rendering do framework.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async getBooks({request, response}) {
-    if(!request.session.user) {
-      response.status(401).json({unauthorized: true});
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Próximo passo

⚔ Aprenda sobre estilos.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/requisicao-e-resposta-do-servidor/index.html b/docs/pt-br/requisicao-e-resposta-do-servidor/index.html deleted file mode 100644 index 34a63393..00000000 --- a/docs/pt-br/requisicao-e-resposta-do-servidor/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - Requisição e resposta do servidor - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Requisição e resposta do servidor

A key do servidor

A key do servidor é um proxy em volta de uma instância do Express que roda por baixo dos panos.

-

O objeto do servidor está presenta apenas no contexto do servidor.

-

As seguintes funções são redirecionadas para o servidor Express:

-
    -
  • get
  • -
  • post
  • -
  • put
  • -
  • patch
  • -
  • delete
  • -
  • options
  • -
  • head
  • -
  • use
  • -
-
-

✨ Se você quer aprender como fazer uma API com Nullstack, este é o caminho.

-
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.get('/api/books', (request, response) => {
-      response.json({books: []});
-    });
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Outras keys disponíveis são:

-
    -
  • port: integer
  • -
  • maximumPayloadSize: string
  • -
  • cors: object
  • -
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.port = 3000;
-    server.maximumPayloadSize = '5mb';
-    server.cors = {
-      origin: 'http://localhost:6969',
-      optionsSuccessStatus: 200
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

O objeto cors será passado como argumento para o plugin do cors no express.

-

Requisição e resposta

Todo contexto de função do servidor é mesclado com os objetos request e response originais do Express.

-

Se você der uma resposta manualmente ela irá sobrescrever a response server-side rendering do framework.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async getBooks({request, response}) {
-    if(!request.session.user) {
-      response.status(401).json({unauthorized: true});
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Próximo passo

⚔ Aprenda sobre estilos.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/requisicao-e-resposta-do-servidor/index.json b/docs/pt-br/requisicao-e-resposta-do-servidor/index.json deleted file mode 100644 index 57ca93f9..00000000 --- a/docs/pt-br/requisicao-e-resposta-do-servidor/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Requisição e resposta do servidor","html":"

A key do servidor

A key do servidor é um proxy em volta de uma instância do Express que roda por baixo dos panos.

\n

O objeto do servidor está presenta apenas no contexto do servidor.

\n

As seguintes funções são redirecionadas para o servidor Express:

\n
    \n
  • get
  • \n
  • post
  • \n
  • put
  • \n
  • patch
  • \n
  • delete
  • \n
  • options
  • \n
  • head
  • \n
  • use
  • \n
\n
\n

✨ Se você quer aprender como fazer uma API com Nullstack, este é o caminho.

\n
\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({server}) {\n    server.get('/api/books', (request, response) => {\n      response.json({books: []});\n    });\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

Outras keys disponíveis são:

\n
    \n
  • port: integer
  • \n
  • maximumPayloadSize: string
  • \n
  • cors: object
  • \n
\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({server}) {\n    server.port = 3000;\n    server.maximumPayloadSize = '5mb';\n    server.cors = {\n      origin: 'http://localhost:6969',\n      optionsSuccessStatus: 200\n    }\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

O objeto cors será passado como argumento para o plugin do cors no express.

\n

Requisição e resposta

Todo contexto de função do servidor é mesclado com os objetos request e response originais do Express.

\n

Se você der uma resposta manualmente ela irá sobrescrever a response server-side rendering do framework.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async getBooks({request, response}) {\n    if(!request.session.user) {\n      response.status(401).json({unauthorized: true});\n    }\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

Próximo passo

⚔ Aprenda sobre estilos.

\n","description":"A key do servidor é um proxy em volta da instância do express, que roda o Nullstack por baixo dos panos"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Requisição e resposta do servidor - Nullstack","description":"A key do servidor é um proxy em volta da instância do express, que roda o Nullstack por baixo dos panos"}} \ No newline at end of file diff --git a/docs/pt-br/rotas-e-parametros.html b/docs/pt-br/rotas-e-parametros.html deleted file mode 100644 index f01f97bb..00000000 --- a/docs/pt-br/rotas-e-parametros.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Rotas e Parâmetros - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Rotas e Parâmetros

Nullstack tem rotas embutidas, não faria sentido não ser assim já que se espera que aplicações web tenham hyperlinks.

-

Qualquer tag pode receber um atributo route, seja um componente, componente interno ou uma tag HTML simples.

-
import Nullstack from 'nullstack';
-import Page from './Page';
-
-class Application extends Nullstack {
-
-  renderHome() {
-    return (
-      <section> Home </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page" />
-        <abbr route="/abbreviations"> Abreviações </abbr>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Links no Nullstack são tags a simples com o valor de href começando com "/".

-
<a href="/page/about"> Página About </a>
-
-
-

💡 No lado do cliente o evento de clique modificará o histórico sem recarregar a página.

-
-
-

✨ Você ainda pode atribuir seu próprio evento de clique para a tag sem perder o comportamento do framework.

-
-

Parâmetros

A chave params é um proxy de objeto injetado em cada instância de cliente.

-

Cada parâmetro da string de query é mapeado para esse objeto.

-

Por padrão qualquer chave requisitada deste objeto retornará uma string.

-

Se o valor for undefined retornará uma string vazia.

-

Se o valor for true ou false retornará um boleano, ao invés de uma string.

-
-

🐱‍💻 Abaixo um exemplo que visita "/books?expanded=true&page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    if(params.expanded) {
-      const page = parseInt(params.page) || 1;
-      this.books = await this.getBooks({page});
-    }
-  }
-
-}
-
-export default Books;
-
-

Realizar atribuição para uma chave de params causará um redirecionamento para a rota com os parâmetros atualizados.

-

Quando realizar atribuição para um parâmetro, o valor será convertido para JSON antes de ser definido.

-
-

💡 Redirecionamentos funcionam em lotes, então não há perca de performance em multiplas atribuições.

-
-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  handleClick({params}) {
-    params.filter = '';
-    params.page = 1;
-  }
-
-}
-
-export default Paginator;
-
-

Atribuir uma string vazia a um parâmetro irá removê-lo da url.

-

Segmentos Dinâmicos

Parte da rota pode ser uma expressão começada com ":" segida por um nome de parâmetro.

-

Esse valor será comparado com qualquer string na mesma posição de diretório.

-

O valor da string na URL será atribuído para o contexto, parâmetros e funções abaixo desse ponto na hierarquia terão acesso a nova chave.

-
-

🐱‍💻 Abaixo um exemplo que visita "/category/suspense?page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    const page = parseInt(params.page) || 1;
-    const category = params.slug;
-    this.books = await this.getBooks({category, page});
-  }
-
-}
-
-export default Books;
-
-
import Nullstack from 'nullstack';
-import Books from './Books';
-
-class Application extends Nullstack {
-
-  render() {
-    <main>
-      <Books route="/category/:slug">
-    </main>
-  }
-
-}
-
-export default Application;
-
-

Quando um segmento dinâmico é alterado, como por exemplo mover de "/category/suspense" para "/category/comedy", o componente será desfeito e uma nova instância será criada.

-

Mudar um parâmetro de consulta não re-instnaciará o componente.

-

Os filhos do componente não serão re-instanciados automaticamente, você pode definir a mesma rota para os filhos ou fazer isso manualmente se desejar esse comportamento.

-
-

💡 O comportamento mencionado acima resolve muitos dos problemas que você teria normalmente que lidar manualmente.

-
-

Curingas

Curingas são rotas declaradas com "*" como valor do atributo

-

Essas rotas corresponderão a qualquer coisa se nada acima delas corresponder a URL requisitada.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <div route="*"> Curinga </div>
-      </main>
-    )
-  }
-
-}
-
-

Curingas podem ser prefixados com um segmento.

-
-

✨ Isso é especialmente útil para engines que podem ser montadas em suas aplicações.

-
-
import Nullstack from 'nullstack';
-import Home from './Home';
-import BlogEngine from './BlogEngine';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <BlogEngine route="/blog/*" />
-      </main>
-    )
-  }
-
-}
-
-

Roteador

A chave router é um proxy de objeto injetado em cada instância de cliente.

-

O router tem duas chaves:

-
    -
  • url
  • -
  • path
  • -
-

A chave url retorna tudo depois do domínio, incluindo o caminho e os parâmetros de query como uma string.

-

A chave path retorna apenas o caminho sem os parâmetros de consulta.

-
-

💡 Ambas as chaves acima automaticamente removem a barra final por conveniência.

-
-

Atribuir a url ou path causará redirecionamento.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  prepare({router}) {
-    if(router.path == '/') {
-      router.path = '/dashboard';
-    }
-  }
-
-}
-
-
-

💡 Por baixo dos panos tags a e params usam o router.

-
-

Eventos customizados

Atualizar router.url ou router.path irá gerar um evento personalizado.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({router}) {
-    window.addEventListener(router.event, () => {
-      console.log(router.url);
-    });
-  }
-
-}
-
-export default Analytics;
-
-

Âncoras especiais

Tags de âncora aceitam somente alguns atributos especiais convenientes além do href comum.

-

Você pode atribuir o atributo params com um objeto como valor.

-

O caminho permanecerá o mesmo do caminho atual do roteador, mas os params serão substituídos pelos novos parâmetros que você especificar.

-
<a params={{page: 1}}> Primeira Página </a>
-
-

E você deseja apenas atualizar alguns parâmetros e manter outros, você pode usar o operador javascript spread para isso.

-
<a params={{...params, page: 1}}> Primeira Página </a>
-
-

Você pode definir o atributo path com uma string começando com "/" e sem parâmetros de query.

-

Os parâmetros permanecerão os mesmos, mas, o path será atualizado.

-
<a path="/category/suspense"> Livros de Suspense </a>
-
-

Ambos os atributos acima podem ser utilizados ao mesmo tempo.

-
<a path="/category/suspense" params={{...params, page: 1}}> Livros de Suspense </a>
-
-

Rotas aninhadas

A primeira rota a ser correspondida será renderizada.

-

Os outros elementos com uma rota não serão renderizados, no entanto, os elementos no mesmo nível sem um atributo route serão renderizados normalmente.

-

O roteador irá procurar uma rota por nível de profundidade DOM, isso permite que você tenha um comportamento de roteamento aninhado.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  renderPage() {
-    return (
-      <section>
-        <div route="/page/about"> About Page </div>
-        <div route="/page/contact"> Contact Page </div>
-      </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page/:slug" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Próximo passo

⚔ Aprenda sobre vínculos bidirecionais.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/rotas-e-parametros/index.html b/docs/pt-br/rotas-e-parametros/index.html deleted file mode 100644 index f01f97bb..00000000 --- a/docs/pt-br/rotas-e-parametros/index.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Rotas e Parâmetros - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Rotas e Parâmetros

Nullstack tem rotas embutidas, não faria sentido não ser assim já que se espera que aplicações web tenham hyperlinks.

-

Qualquer tag pode receber um atributo route, seja um componente, componente interno ou uma tag HTML simples.

-
import Nullstack from 'nullstack';
-import Page from './Page';
-
-class Application extends Nullstack {
-
-  renderHome() {
-    return (
-      <section> Home </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page" />
-        <abbr route="/abbreviations"> Abreviações </abbr>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Links no Nullstack são tags a simples com o valor de href começando com "/".

-
<a href="/page/about"> Página About </a>
-
-
-

💡 No lado do cliente o evento de clique modificará o histórico sem recarregar a página.

-
-
-

✨ Você ainda pode atribuir seu próprio evento de clique para a tag sem perder o comportamento do framework.

-
-

Parâmetros

A chave params é um proxy de objeto injetado em cada instância de cliente.

-

Cada parâmetro da string de query é mapeado para esse objeto.

-

Por padrão qualquer chave requisitada deste objeto retornará uma string.

-

Se o valor for undefined retornará uma string vazia.

-

Se o valor for true ou false retornará um boleano, ao invés de uma string.

-
-

🐱‍💻 Abaixo um exemplo que visita "/books?expanded=true&page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    if(params.expanded) {
-      const page = parseInt(params.page) || 1;
-      this.books = await this.getBooks({page});
-    }
-  }
-
-}
-
-export default Books;
-
-

Realizar atribuição para uma chave de params causará um redirecionamento para a rota com os parâmetros atualizados.

-

Quando realizar atribuição para um parâmetro, o valor será convertido para JSON antes de ser definido.

-
-

💡 Redirecionamentos funcionam em lotes, então não há perca de performance em multiplas atribuições.

-
-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  handleClick({params}) {
-    params.filter = '';
-    params.page = 1;
-  }
-
-}
-
-export default Paginator;
-
-

Atribuir uma string vazia a um parâmetro irá removê-lo da url.

-

Segmentos Dinâmicos

Parte da rota pode ser uma expressão começada com ":" segida por um nome de parâmetro.

-

Esse valor será comparado com qualquer string na mesma posição de diretório.

-

O valor da string na URL será atribuído para o contexto, parâmetros e funções abaixo desse ponto na hierarquia terão acesso a nova chave.

-
-

🐱‍💻 Abaixo um exemplo que visita "/category/suspense?page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    const page = parseInt(params.page) || 1;
-    const category = params.slug;
-    this.books = await this.getBooks({category, page});
-  }
-
-}
-
-export default Books;
-
-
import Nullstack from 'nullstack';
-import Books from './Books';
-
-class Application extends Nullstack {
-
-  render() {
-    <main>
-      <Books route="/category/:slug">
-    </main>
-  }
-
-}
-
-export default Application;
-
-

Quando um segmento dinâmico é alterado, como por exemplo mover de "/category/suspense" para "/category/comedy", o componente será desfeito e uma nova instância será criada.

-

Mudar um parâmetro de consulta não re-instnaciará o componente.

-

Os filhos do componente não serão re-instanciados automaticamente, você pode definir a mesma rota para os filhos ou fazer isso manualmente se desejar esse comportamento.

-
-

💡 O comportamento mencionado acima resolve muitos dos problemas que você teria normalmente que lidar manualmente.

-
-

Curingas

Curingas são rotas declaradas com "*" como valor do atributo

-

Essas rotas corresponderão a qualquer coisa se nada acima delas corresponder a URL requisitada.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <div route="*"> Curinga </div>
-      </main>
-    )
-  }
-
-}
-
-

Curingas podem ser prefixados com um segmento.

-
-

✨ Isso é especialmente útil para engines que podem ser montadas em suas aplicações.

-
-
import Nullstack from 'nullstack';
-import Home from './Home';
-import BlogEngine from './BlogEngine';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <BlogEngine route="/blog/*" />
-      </main>
-    )
-  }
-
-}
-
-

Roteador

A chave router é um proxy de objeto injetado em cada instância de cliente.

-

O router tem duas chaves:

-
    -
  • url
  • -
  • path
  • -
-

A chave url retorna tudo depois do domínio, incluindo o caminho e os parâmetros de query como uma string.

-

A chave path retorna apenas o caminho sem os parâmetros de consulta.

-
-

💡 Ambas as chaves acima automaticamente removem a barra final por conveniência.

-
-

Atribuir a url ou path causará redirecionamento.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  prepare({router}) {
-    if(router.path == '/') {
-      router.path = '/dashboard';
-    }
-  }
-
-}
-
-
-

💡 Por baixo dos panos tags a e params usam o router.

-
-

Eventos customizados

Atualizar router.url ou router.path irá gerar um evento personalizado.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({router}) {
-    window.addEventListener(router.event, () => {
-      console.log(router.url);
-    });
-  }
-
-}
-
-export default Analytics;
-
-

Âncoras especiais

Tags de âncora aceitam somente alguns atributos especiais convenientes além do href comum.

-

Você pode atribuir o atributo params com um objeto como valor.

-

O caminho permanecerá o mesmo do caminho atual do roteador, mas os params serão substituídos pelos novos parâmetros que você especificar.

-
<a params={{page: 1}}> Primeira Página </a>
-
-

E você deseja apenas atualizar alguns parâmetros e manter outros, você pode usar o operador javascript spread para isso.

-
<a params={{...params, page: 1}}> Primeira Página </a>
-
-

Você pode definir o atributo path com uma string começando com "/" e sem parâmetros de query.

-

Os parâmetros permanecerão os mesmos, mas, o path será atualizado.

-
<a path="/category/suspense"> Livros de Suspense </a>
-
-

Ambos os atributos acima podem ser utilizados ao mesmo tempo.

-
<a path="/category/suspense" params={{...params, page: 1}}> Livros de Suspense </a>
-
-

Rotas aninhadas

A primeira rota a ser correspondida será renderizada.

-

Os outros elementos com uma rota não serão renderizados, no entanto, os elementos no mesmo nível sem um atributo route serão renderizados normalmente.

-

O roteador irá procurar uma rota por nível de profundidade DOM, isso permite que você tenha um comportamento de roteamento aninhado.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  renderPage() {
-    return (
-      <section>
-        <div route="/page/about"> About Page </div>
-        <div route="/page/contact"> Contact Page </div>
-      </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page/:slug" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Próximo passo

⚔ Aprenda sobre vínculos bidirecionais.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/rotas-e-parametros/index.json b/docs/pt-br/rotas-e-parametros/index.json deleted file mode 100644 index 818acee0..00000000 --- a/docs/pt-br/rotas-e-parametros/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Rotas e Parâmetros","html":"

Nullstack tem rotas embutidas, não faria sentido não ser assim já que se espera que aplicações web tenham hyperlinks.

\n

Qualquer tag pode receber um atributo route, seja um componente, componente interno ou uma tag HTML simples.

\n
import Nullstack from 'nullstack';\nimport Page from './Page';\n\nclass Application extends Nullstack {\n\n  renderHome() {\n    return (\n      <section> Home </section>\n    )\n  }\n \n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <Page route=\"/page\" />\n        <abbr route=\"/abbreviations\"> Abreviações </abbr>\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Links

Links no Nullstack são tags a simples com o valor de href começando com "/".

\n
<a href=\"/page/about\"> Página About </a>\n
\n
\n

💡 No lado do cliente o evento de clique modificará o histórico sem recarregar a página.

\n
\n
\n

✨ Você ainda pode atribuir seu próprio evento de clique para a tag sem perder o comportamento do framework.

\n
\n

Parâmetros

A chave params é um proxy de objeto injetado em cada instância de cliente.

\n

Cada parâmetro da string de query é mapeado para esse objeto.

\n

Por padrão qualquer chave requisitada deste objeto retornará uma string.

\n

Se o valor for undefined retornará uma string vazia.

\n

Se o valor for true ou false retornará um boleano, ao invés de uma string.

\n
\n

🐱‍💻 Abaixo um exemplo que visita "/books?expanded=true&page=2":

\n
\n
import Nullstack from 'nullstack';\n\nclass Books extends Nullstack {\n\n  async initiate({params}) {\n    if(params.expanded) {\n      const page = parseInt(params.page) || 1;\n      this.books = await this.getBooks({page});\n    }\n  }\n\n}\n\nexport default Books;\n
\n

Realizar atribuição para uma chave de params causará um redirecionamento para a rota com os parâmetros atualizados.

\n

Quando realizar atribuição para um parâmetro, o valor será convertido para JSON antes de ser definido.

\n
\n

💡 Redirecionamentos funcionam em lotes, então não há perca de performance em multiplas atribuições.

\n
\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n\n  handleClick({params}) {\n    params.filter = '';\n    params.page = 1;\n  }\n\n}\n\nexport default Paginator;\n
\n

Atribuir uma string vazia a um parâmetro irá removê-lo da url.

\n

Segmentos Dinâmicos

Parte da rota pode ser uma expressão começada com ":" segida por um nome de parâmetro.

\n

Esse valor será comparado com qualquer string na mesma posição de diretório.

\n

O valor da string na URL será atribuído para o contexto, parâmetros e funções abaixo desse ponto na hierarquia terão acesso a nova chave.

\n
\n

🐱‍💻 Abaixo um exemplo que visita "/category/suspense?page=2":

\n
\n
import Nullstack from 'nullstack';\n\nclass Books extends Nullstack {\n\n  async initiate({params}) {\n    const page = parseInt(params.page) || 1;\n    const category = params.slug;\n    this.books = await this.getBooks({category, page});\n  }\n\n}\n\nexport default Books;\n
\n
import Nullstack from 'nullstack';\nimport Books from './Books';\n\nclass Application extends Nullstack {\n\n  render() {\n    <main>\n      <Books route=\"/category/:slug\">\n    </main>\n  }\n\n}\n\nexport default Application;\n
\n

Quando um segmento dinâmico é alterado, como por exemplo mover de "/category/suspense" para "/category/comedy", o componente será desfeito e uma nova instância será criada.

\n

Mudar um parâmetro de consulta não re-instnaciará o componente.

\n

Os filhos do componente não serão re-instanciados automaticamente, você pode definir a mesma rota para os filhos ou fazer isso manualmente se desejar esse comportamento.

\n
\n

💡 O comportamento mencionado acima resolve muitos dos problemas que você teria normalmente que lidar manualmente.

\n
\n

Curingas

Curingas são rotas declaradas com "*" como valor do atributo

\n

Essas rotas corresponderão a qualquer coisa se nada acima delas corresponder a URL requisitada.

\n
import Nullstack from 'nullstack';\nimport Home from './Home';\n\nclass Application extends Nullstack {\n\n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <div route=\"*\"> Curinga </div>\n      </main>\n    )\n  }\n\n}\n
\n

Curingas podem ser prefixados com um segmento.

\n
\n

✨ Isso é especialmente útil para engines que podem ser montadas em suas aplicações.

\n
\n
import Nullstack from 'nullstack';\nimport Home from './Home';\nimport BlogEngine from './BlogEngine';\n\nclass Application extends Nullstack {\n\n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <BlogEngine route=\"/blog/*\" />\n      </main>\n    )\n  }\n\n}\n
\n

Roteador

A chave router é um proxy de objeto injetado em cada instância de cliente.

\n

O router tem duas chaves:

\n
    \n
  • url
  • \n
  • path
  • \n
\n

A chave url retorna tudo depois do domínio, incluindo o caminho e os parâmetros de query como uma string.

\n

A chave path retorna apenas o caminho sem os parâmetros de consulta.

\n
\n

💡 Ambas as chaves acima automaticamente removem a barra final por conveniência.

\n
\n

Atribuir a url ou path causará redirecionamento.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  prepare({router}) {\n    if(router.path == '/') {\n      router.path = '/dashboard';\n    }\n  }\n\n}\n
\n
\n

💡 Por baixo dos panos tags a e params usam o router.

\n
\n

Eventos customizados

Atualizar router.url ou router.path irá gerar um evento personalizado.

\n
import Nullstack from 'nullstack';\n\nclass Analytics extends Nullstack {\n\n  hydrate({router}) {\n    window.addEventListener(router.event, () => {\n      console.log(router.url);\n    });\n  }\n\n}\n\nexport default Analytics;\n
\n

Âncoras especiais

Tags de âncora aceitam somente alguns atributos especiais convenientes além do href comum.

\n

Você pode atribuir o atributo params com um objeto como valor.

\n

O caminho permanecerá o mesmo do caminho atual do roteador, mas os params serão substituídos pelos novos parâmetros que você especificar.

\n
<a params={{page: 1}}> Primeira Página </a>\n
\n

E você deseja apenas atualizar alguns parâmetros e manter outros, você pode usar o operador javascript spread para isso.

\n
<a params={{...params, page: 1}}> Primeira Página </a>\n
\n

Você pode definir o atributo path com uma string começando com "/" e sem parâmetros de query.

\n

Os parâmetros permanecerão os mesmos, mas, o path será atualizado.

\n
<a path=\"/category/suspense\"> Livros de Suspense </a>\n
\n

Ambos os atributos acima podem ser utilizados ao mesmo tempo.

\n
<a path=\"/category/suspense\" params={{...params, page: 1}}> Livros de Suspense </a>\n
\n

Rotas aninhadas

A primeira rota a ser correspondida será renderizada.

\n

Os outros elementos com uma rota não serão renderizados, no entanto, os elementos no mesmo nível sem um atributo route serão renderizados normalmente.

\n

O roteador irá procurar uma rota por nível de profundidade DOM, isso permite que você tenha um comportamento de roteamento aninhado.

\n
import Nullstack from 'nullstack';\nimport Home from './Home';\n\nclass Application extends Nullstack {\n\n  renderPage() {\n    return (\n      <section>\n        <div route=\"/page/about\"> About Page </div>\n        <div route=\"/page/contact\"> Contact Page </div>\n      </section>\n    )\n  }\n \n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <Page route=\"/page/:slug\" />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Próximo passo

⚔ Aprenda sobre vínculos bidirecionais.

\n","description":"Nullstack tem rotas embutidas, não faria sentido não ser assim já que se espera que aplicações web tenham hyperlinks."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Rotas e Parâmetros - Nullstack","description":"Nullstack tem rotas embutidas, não faria sentido não ser assim já que se espera que aplicações web tenham hyperlinks."}} \ No newline at end of file diff --git a/docs/pt-br/service-worker.html b/docs/pt-br/service-worker.html deleted file mode 100644 index bb009504..00000000 --- a/docs/pt-br/service-worker.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - Contexto Service Worker - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Service Worker

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite no contexto do server
  • -
  • readonly no contexto do client
  • -
-

Ele te dá controle granular do comportamento do seu PWA.

-

Chaves do worker serão usadas para gerar o arquivo do service worker e devem ser setadas durante o processo de inicialização.

-

Chaves do worker são congeladas após o processo de inicialização.

-

As seguintes keys estão disponíveis no objeto durante a inicialização:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • headers: object
  • -
-

A chave enabled define se o service worker será registrado automaticamente pelo Nullstack.

-

Por padrão a chave enabled é setada como true no modo de produção e false no modo de desenvolvimento.

-

O array preload é composto por caminhos que serão cacheados quando o service worker for instalado.

-

Os assets requeridos para inicializar a aplicação serão pré-carregados automaticamente, e você deverá apenas as páginas extras que você quer que estejam disponíveis em modo offline.

-
import Nullstack from 'nullstack';
-import path from 'path';
-import {readdirSync} from 'fs';
-
-class Application extends Nullstack {
-
-  static async start({worker}) {
-    const articles = readdirSync(path.join(__dirname, '..', 'articles'));
-    worker.preload = [
-      ...articles.map((article) => '/' + article.replace('.md', '')),
-      '/nullstack.svg',
-      '/documentation',
-      '/components'
-    ]
-  }
-  
-  // ...
-
-}
-
-export default Application;
-
-
-

💡 O exemplo acima foi extraido deste repositório e permite que a documentação esteja totalmente acessível em modo offline.

-
-

As seguintes chaves estão disponíveis como readonly no contexto do cliente:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • online: boolean
  • -
  • fetching: boolean
  • -
  • responsive: boolean
  • -
  • installation: BeforeInstallPromptEvent
  • -
  • registration: ServiceWorkerRegistration
  • -
  • loading: object
  • -
-

As seguintes chaves estão disponíveis como readwrite no contexto do cliente:

-
    -
  • headers: object
  • -
-

A chave responsive determina se a aplicação tem todas as respostas necessárias para renderizar a página atual.

-

O Nullstack irá tentar manter sua aplicação respondendo o maior tempo possível e setará a chave para false somente quando não houver mais alternativas de recuperar qualquer resposta da rede ou offline usando a estratégia de busca para o ambiente.

-

A chave online irá monitorar os eventos da rede e re-renderizar a aplicação quando o valor de navigator.onLine mudar.

-

Quando a aplicação voltar a ficar online o Nullstack irá tentar fazer a aplicação responder novamente e re-renderizar se necessário.

-
import Nullstack from 'nullstack';
-// ...
-
-class Application extends Nullstack {
- 
-  // ...
-
-  render({worker}) {
-    if(!worker.responsive) {
-      return <OfflineWarning />
-    }
-    return (
-      <main>
-        <Home route="/" />
-      </main>
-    )
-  }
-
-}
-
-

Você pode acessar a registration e installation do service worker atual pela chave worker para controlar o fluxo do seu PWA.

-

A chave registration se refere ao registro do service worker e só estará disponível uma vez que o processo de registro esteja completo.

-

A chave installation se refere a instalação delegada no evento do prompt e apenas estará disponível se o evento beforeinstallprompt ocorrer.

-
import Nullstack from 'nullstack';
-
-class PWAInstaller extends Nullstack {
-
-  installed = false;
-  hidden = false;
-
-  async prompt({worker}) {
-    try {
-      worker.installation.prompt();
-      const {outcome} = await worker.installation.userChoice;
-      if (outcome === 'accepted') {
-        console.log('User accepted the A2HS prompt');
-      } else {
-        console.log('User dismissed the A2HS prompt');
-      }
-    } finally {
-      this.hidden = true;
-    }
-  }
-  
-  render({worker, project}) {
-    if(this.hidden) return false;
-    if(!worker.installation) return false;
-    return (
-      <div>
-        <img src={project.favicon} />
-        <p> Do you want to add {project.name} to your home screen?</p>
-        <button onclick={this.prompt}> Install </button>
-        <button onclick={{hidden: true}}> Not Now </button>
-      </div>
-    )
-  }
-
-}
-
-export default PWAInstaller;
-
-

Carregando telas

Quando uma função do servidor é chamada o fetching será setado como true até a requisição ser resolvida.

-

Quando uma função do servidor é chamada a chave com o nome da função do servidor invocada será setada como true na chave loading até a requisição ser resolvida.

-

Qualquer chave que for chamada no objeto loading sempre irá retornar um valor booleano ao invés de undefined por consistência.

-

Quando o servidor estiver emulando o contexto do cliente para renderização no lado do servidor, todas as chaves de loading vão sempre retornar false, pulando multiplos ciclos de render por performance.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  static async save() {
-    // ...
-  }
-
-  async submit() {
-    await this.save();
-  }
- 
-  render({worker}) {
-    return (
-      <form onsubmit={this.save}> 
-        {worker.fetching && 
-          <span> loading... </span>
-        }
-        <button disabled={worker.loading.save}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-

Headers customizadas

Você pode usar a chave headers para configurar as headers que o worker usará na requisição para uma função do servidor

-
-

🔥 headers serão ignorados quando uma função do servidor for chamada durante o processo de renderização do lado do servidor

-
-
import Nullstack from 'nullstack';
-
-class LoginPage extends Nullstack {
-
-  // ...
-
-  async submit({worker}) {
-    // ...
-    this.headers['Authorization'] = `Bearer ${token}`;
-    // ...
-  }
-
-  static async authorize({request}) {
-    const authorization = request.headers['Authorization'];
-    // ...
-  }
-  
-  // ...
-
-}
-
-
-export default LoginPage;
-
-
-

✨ Aprenda mais sobre o requisições e respostas do servidor

-
-

Estratégia de renderização Server-side

    -
  • Requisições de diferentes origens serão realizadas normalmente;
  • -
  • Requisições diferentes do método GET serão realizadas normalmente;
  • -
  • Assets com Fingerprints serão carregados no cache no momento da instalação;
  • -
  • Assets com Fingerprints serão carregados do cache primeiro, e só então retornados para a rede, se necessário;
  • -
  • Caminhos com uma extensão serão recuperados e atualizarão o cache em segundo plano para uma requisição subsequente;
  • -
  • Os caminhos navegados serão carregados da rede e se falhar serão retornados do cache para a página na qual o worker.responsive e o worker.online estiverem setados como false;
  • -
-

Estratégia de geração de site estático

    -
  • Requisições de diferentes origens serão realizadas normalmente;
  • -
  • Requisições diferentes do método GET serão realizadas normalmente;
  • -
  • Assets com Fingerprints serão carregados no cache no momento da instalação;
  • -
  • Assets com Fingerprints serão carregados do cache primeiro, e só então retornados para a rede, se necessário;
  • -
  • Caminhos com uma extensão serão recuperaados e atualizarão o cache em segundo plano para uma requisição subsequente;
  • -
  • A página inicial será carregada na rede primeiro, e se necessário será retornada uma cópia em cache;
  • -
  • Caminhos navegados irão carregar apenas os dados da API estática e mesclar com o template da aplicação para gerar a resposta.
  • -
  • Navegar para uma rota estática irá fazer cache apenas dos dados daquela página;
  • -
  • Quando os dados estiverem indisponíveis no cache ou na rede irá retornar uma página na qual worker.responsive e worker.online estiverem setados como false;
  • -
-

Estratégia customizada

O Nullstack irá instalar automaticamente seu service worker se enabled estiver setado como true com os seguintes eventos:

-
    -
  • install
  • -
  • activate
  • -
  • fetch
  • -
-

Você pode sobreescrever qualquer um desses eventos criando um service-worker.js na pasta public;

-

Se qualquer uma das palavras chaves acima for encontrada o Nullstack injetará sua função no código do service worker ao invés do padrão.

-

Por conveniência uma chave chamada context é injetada no self do service worker com as seguintes chaves:

- -
function activate(event) {
-  event.waitUntil(async function() {
-    const cacheNames = await caches.keys();
-    const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key);
-    await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName)));
-    if (self.registration.navigationPreload) {
-      await self.registration.navigationPreload.enable();
-    }
-    self.clients.claim();
-  }());
-}
-
-self.addEventListener('activate', activate);
-
-
-

💡 O exemplo acima foi extraido do service worker gerado e usa self.context.enviroment.key

-
-

Próximo passo

⚔ Aprenda Como fazer o deploy de uma aplicação Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/service-worker/index.html b/docs/pt-br/service-worker/index.html deleted file mode 100644 index bb009504..00000000 --- a/docs/pt-br/service-worker/index.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - Contexto Service Worker - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Contexto Service Worker

    -
  • Tipo: object
  • -
  • Origem: Contexto Nullstack
  • -
  • Disponibilidade: server/client
  • -
  • readwrite no contexto do server
  • -
  • readonly no contexto do client
  • -
-

Ele te dá controle granular do comportamento do seu PWA.

-

Chaves do worker serão usadas para gerar o arquivo do service worker e devem ser setadas durante o processo de inicialização.

-

Chaves do worker são congeladas após o processo de inicialização.

-

As seguintes keys estão disponíveis no objeto durante a inicialização:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • headers: object
  • -
-

A chave enabled define se o service worker será registrado automaticamente pelo Nullstack.

-

Por padrão a chave enabled é setada como true no modo de produção e false no modo de desenvolvimento.

-

O array preload é composto por caminhos que serão cacheados quando o service worker for instalado.

-

Os assets requeridos para inicializar a aplicação serão pré-carregados automaticamente, e você deverá apenas as páginas extras que você quer que estejam disponíveis em modo offline.

-
import Nullstack from 'nullstack';
-import path from 'path';
-import {readdirSync} from 'fs';
-
-class Application extends Nullstack {
-
-  static async start({worker}) {
-    const articles = readdirSync(path.join(__dirname, '..', 'articles'));
-    worker.preload = [
-      ...articles.map((article) => '/' + article.replace('.md', '')),
-      '/nullstack.svg',
-      '/documentation',
-      '/components'
-    ]
-  }
-  
-  // ...
-
-}
-
-export default Application;
-
-
-

💡 O exemplo acima foi extraido deste repositório e permite que a documentação esteja totalmente acessível em modo offline.

-
-

As seguintes chaves estão disponíveis como readonly no contexto do cliente:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • online: boolean
  • -
  • fetching: boolean
  • -
  • responsive: boolean
  • -
  • installation: BeforeInstallPromptEvent
  • -
  • registration: ServiceWorkerRegistration
  • -
  • loading: object
  • -
-

As seguintes chaves estão disponíveis como readwrite no contexto do cliente:

-
    -
  • headers: object
  • -
-

A chave responsive determina se a aplicação tem todas as respostas necessárias para renderizar a página atual.

-

O Nullstack irá tentar manter sua aplicação respondendo o maior tempo possível e setará a chave para false somente quando não houver mais alternativas de recuperar qualquer resposta da rede ou offline usando a estratégia de busca para o ambiente.

-

A chave online irá monitorar os eventos da rede e re-renderizar a aplicação quando o valor de navigator.onLine mudar.

-

Quando a aplicação voltar a ficar online o Nullstack irá tentar fazer a aplicação responder novamente e re-renderizar se necessário.

-
import Nullstack from 'nullstack';
-// ...
-
-class Application extends Nullstack {
- 
-  // ...
-
-  render({worker}) {
-    if(!worker.responsive) {
-      return <OfflineWarning />
-    }
-    return (
-      <main>
-        <Home route="/" />
-      </main>
-    )
-  }
-
-}
-
-

Você pode acessar a registration e installation do service worker atual pela chave worker para controlar o fluxo do seu PWA.

-

A chave registration se refere ao registro do service worker e só estará disponível uma vez que o processo de registro esteja completo.

-

A chave installation se refere a instalação delegada no evento do prompt e apenas estará disponível se o evento beforeinstallprompt ocorrer.

-
import Nullstack from 'nullstack';
-
-class PWAInstaller extends Nullstack {
-
-  installed = false;
-  hidden = false;
-
-  async prompt({worker}) {
-    try {
-      worker.installation.prompt();
-      const {outcome} = await worker.installation.userChoice;
-      if (outcome === 'accepted') {
-        console.log('User accepted the A2HS prompt');
-      } else {
-        console.log('User dismissed the A2HS prompt');
-      }
-    } finally {
-      this.hidden = true;
-    }
-  }
-  
-  render({worker, project}) {
-    if(this.hidden) return false;
-    if(!worker.installation) return false;
-    return (
-      <div>
-        <img src={project.favicon} />
-        <p> Do you want to add {project.name} to your home screen?</p>
-        <button onclick={this.prompt}> Install </button>
-        <button onclick={{hidden: true}}> Not Now </button>
-      </div>
-    )
-  }
-
-}
-
-export default PWAInstaller;
-
-

Carregando telas

Quando uma função do servidor é chamada o fetching será setado como true até a requisição ser resolvida.

-

Quando uma função do servidor é chamada a chave com o nome da função do servidor invocada será setada como true na chave loading até a requisição ser resolvida.

-

Qualquer chave que for chamada no objeto loading sempre irá retornar um valor booleano ao invés de undefined por consistência.

-

Quando o servidor estiver emulando o contexto do cliente para renderização no lado do servidor, todas as chaves de loading vão sempre retornar false, pulando multiplos ciclos de render por performance.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  static async save() {
-    // ...
-  }
-
-  async submit() {
-    await this.save();
-  }
- 
-  render({worker}) {
-    return (
-      <form onsubmit={this.save}> 
-        {worker.fetching && 
-          <span> loading... </span>
-        }
-        <button disabled={worker.loading.save}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-

Headers customizadas

Você pode usar a chave headers para configurar as headers que o worker usará na requisição para uma função do servidor

-
-

🔥 headers serão ignorados quando uma função do servidor for chamada durante o processo de renderização do lado do servidor

-
-
import Nullstack from 'nullstack';
-
-class LoginPage extends Nullstack {
-
-  // ...
-
-  async submit({worker}) {
-    // ...
-    this.headers['Authorization'] = `Bearer ${token}`;
-    // ...
-  }
-
-  static async authorize({request}) {
-    const authorization = request.headers['Authorization'];
-    // ...
-  }
-  
-  // ...
-
-}
-
-
-export default LoginPage;
-
-
-

✨ Aprenda mais sobre o requisições e respostas do servidor

-
-

Estratégia de renderização Server-side

    -
  • Requisições de diferentes origens serão realizadas normalmente;
  • -
  • Requisições diferentes do método GET serão realizadas normalmente;
  • -
  • Assets com Fingerprints serão carregados no cache no momento da instalação;
  • -
  • Assets com Fingerprints serão carregados do cache primeiro, e só então retornados para a rede, se necessário;
  • -
  • Caminhos com uma extensão serão recuperados e atualizarão o cache em segundo plano para uma requisição subsequente;
  • -
  • Os caminhos navegados serão carregados da rede e se falhar serão retornados do cache para a página na qual o worker.responsive e o worker.online estiverem setados como false;
  • -
-

Estratégia de geração de site estático

    -
  • Requisições de diferentes origens serão realizadas normalmente;
  • -
  • Requisições diferentes do método GET serão realizadas normalmente;
  • -
  • Assets com Fingerprints serão carregados no cache no momento da instalação;
  • -
  • Assets com Fingerprints serão carregados do cache primeiro, e só então retornados para a rede, se necessário;
  • -
  • Caminhos com uma extensão serão recuperaados e atualizarão o cache em segundo plano para uma requisição subsequente;
  • -
  • A página inicial será carregada na rede primeiro, e se necessário será retornada uma cópia em cache;
  • -
  • Caminhos navegados irão carregar apenas os dados da API estática e mesclar com o template da aplicação para gerar a resposta.
  • -
  • Navegar para uma rota estática irá fazer cache apenas dos dados daquela página;
  • -
  • Quando os dados estiverem indisponíveis no cache ou na rede irá retornar uma página na qual worker.responsive e worker.online estiverem setados como false;
  • -
-

Estratégia customizada

O Nullstack irá instalar automaticamente seu service worker se enabled estiver setado como true com os seguintes eventos:

-
    -
  • install
  • -
  • activate
  • -
  • fetch
  • -
-

Você pode sobreescrever qualquer um desses eventos criando um service-worker.js na pasta public;

-

Se qualquer uma das palavras chaves acima for encontrada o Nullstack injetará sua função no código do service worker ao invés do padrão.

-

Por conveniência uma chave chamada context é injetada no self do service worker com as seguintes chaves:

- -
function activate(event) {
-  event.waitUntil(async function() {
-    const cacheNames = await caches.keys();
-    const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key);
-    await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName)));
-    if (self.registration.navigationPreload) {
-      await self.registration.navigationPreload.enable();
-    }
-    self.clients.claim();
-  }());
-}
-
-self.addEventListener('activate', activate);
-
-
-

💡 O exemplo acima foi extraido do service worker gerado e usa self.context.enviroment.key

-
-

Próximo passo

⚔ Aprenda Como fazer o deploy de uma aplicação Nullstack.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/service-worker/index.json b/docs/pt-br/service-worker/index.json deleted file mode 100644 index 07a2580b..00000000 --- a/docs/pt-br/service-worker/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Contexto Service Worker","html":"
    \n
  • Tipo: object
  • \n
  • Origem: Contexto Nullstack
  • \n
  • Disponibilidade: server/client
  • \n
  • readwrite no contexto do server
  • \n
  • readonly no contexto do client
  • \n
\n

Ele te dá controle granular do comportamento do seu PWA.

\n

Chaves do worker serão usadas para gerar o arquivo do service worker e devem ser setadas durante o processo de inicialização.

\n

Chaves do worker são congeladas após o processo de inicialização.

\n

As seguintes keys estão disponíveis no objeto durante a inicialização:

\n
    \n
  • enabled: boolean
  • \n
  • preload: string array (relative paths)
  • \n
  • headers: object
  • \n
\n

A chave enabled define se o service worker será registrado automaticamente pelo Nullstack.

\n

Por padrão a chave enabled é setada como true no modo de produção e false no modo de desenvolvimento.

\n

O array preload é composto por caminhos que serão cacheados quando o service worker for instalado.

\n

Os assets requeridos para inicializar a aplicação serão pré-carregados automaticamente, e você deverá apenas as páginas extras que você quer que estejam disponíveis em modo offline.

\n
import Nullstack from 'nullstack';\nimport path from 'path';\nimport {readdirSync} from 'fs';\n\nclass Application extends Nullstack {\n\n  static async start({worker}) {\n    const articles = readdirSync(path.join(__dirname, '..', 'articles'));\n    worker.preload = [\n      ...articles.map((article) => '/' + article.replace('.md', '')),\n      '/nullstack.svg',\n      '/documentation',\n      '/components'\n    ]\n  }\n  \n  // ...\n\n}\n\nexport default Application;\n
\n
\n

💡 O exemplo acima foi extraido deste repositório e permite que a documentação esteja totalmente acessível em modo offline.

\n
\n

As seguintes chaves estão disponíveis como readonly no contexto do cliente:

\n
    \n
  • enabled: boolean
  • \n
  • preload: string array (relative paths)
  • \n
  • online: boolean
  • \n
  • fetching: boolean
  • \n
  • responsive: boolean
  • \n
  • installation: BeforeInstallPromptEvent
  • \n
  • registration: ServiceWorkerRegistration
  • \n
  • loading: object
  • \n
\n

As seguintes chaves estão disponíveis como readwrite no contexto do cliente:

\n
    \n
  • headers: object
  • \n
\n

A chave responsive determina se a aplicação tem todas as respostas necessárias para renderizar a página atual.

\n

O Nullstack irá tentar manter sua aplicação respondendo o maior tempo possível e setará a chave para false somente quando não houver mais alternativas de recuperar qualquer resposta da rede ou offline usando a estratégia de busca para o ambiente.

\n

A chave online irá monitorar os eventos da rede e re-renderizar a aplicação quando o valor de navigator.onLine mudar.

\n

Quando a aplicação voltar a ficar online o Nullstack irá tentar fazer a aplicação responder novamente e re-renderizar se necessário.

\n
import Nullstack from 'nullstack';\n// ...\n\nclass Application extends Nullstack {\n \n  // ...\n\n  render({worker}) {\n    if(!worker.responsive) {\n      return <OfflineWarning />\n    }\n    return (\n      <main>\n        <Home route=\"/\" />\n      </main>\n    )\n  }\n\n}\n
\n

Você pode acessar a registration e installation do service worker atual pela chave worker para controlar o fluxo do seu PWA.

\n

A chave registration se refere ao registro do service worker e só estará disponível uma vez que o processo de registro esteja completo.

\n

A chave installation se refere a instalação delegada no evento do prompt e apenas estará disponível se o evento beforeinstallprompt ocorrer.

\n
import Nullstack from 'nullstack';\n\nclass PWAInstaller extends Nullstack {\n\n  installed = false;\n  hidden = false;\n\n  async prompt({worker}) {\n    try {\n      worker.installation.prompt();\n      const {outcome} = await worker.installation.userChoice;\n      if (outcome === 'accepted') {\n        console.log('User accepted the A2HS prompt');\n      } else {\n        console.log('User dismissed the A2HS prompt');\n      }\n    } finally {\n      this.hidden = true;\n    }\n  }\n  \n  render({worker, project}) {\n    if(this.hidden) return false;\n    if(!worker.installation) return false;\n    return (\n      <div>\n        <img src={project.favicon} />\n        <p> Do you want to add {project.name} to your home screen?</p>\n        <button onclick={this.prompt}> Install </button>\n        <button onclick={{hidden: true}}> Not Now </button>\n      </div>\n    )\n  }\n\n}\n\nexport default PWAInstaller;\n
\n

Carregando telas

Quando uma função do servidor é chamada o fetching será setado como true até a requisição ser resolvida.

\n

Quando uma função do servidor é chamada a chave com o nome da função do servidor invocada será setada como true na chave loading até a requisição ser resolvida.

\n

Qualquer chave que for chamada no objeto loading sempre irá retornar um valor booleano ao invés de undefined por consistência.

\n

Quando o servidor estiver emulando o contexto do cliente para renderização no lado do servidor, todas as chaves de loading vão sempre retornar false, pulando multiplos ciclos de render por performance.

\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n\n  static async save() {\n    // ...\n  }\n\n  async submit() {\n    await this.save();\n  }\n \n  render({worker}) {\n    return (\n      <form onsubmit={this.save}> \n        {worker.fetching && \n          <span> loading... </span>\n        }\n        <button disabled={worker.loading.save}> \n          Save\n        </button>\n      </form>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Headers customizadas

Você pode usar a chave headers para configurar as headers que o worker usará na requisição para uma função do servidor

\n
\n

🔥 headers serão ignorados quando uma função do servidor for chamada durante o processo de renderização do lado do servidor

\n
\n
import Nullstack from 'nullstack';\n\nclass LoginPage extends Nullstack {\n\n  // ...\n\n  async submit({worker}) {\n    // ...\n    this.headers['Authorization'] = `Bearer ${token}`;\n    // ...\n  }\n\n  static async authorize({request}) {\n    const authorization = request.headers['Authorization'];\n    // ...\n  }\n  \n  // ...\n\n}\n\n\nexport default LoginPage;\n
\n
\n

✨ Aprenda mais sobre o requisições e respostas do servidor

\n
\n

Estratégia de renderização Server-side

    \n
  • Requisições de diferentes origens serão realizadas normalmente;
  • \n
  • Requisições diferentes do método GET serão realizadas normalmente;
  • \n
  • Assets com Fingerprints serão carregados no cache no momento da instalação;
  • \n
  • Assets com Fingerprints serão carregados do cache primeiro, e só então retornados para a rede, se necessário;
  • \n
  • Caminhos com uma extensão serão recuperados e atualizarão o cache em segundo plano para uma requisição subsequente;
  • \n
  • Os caminhos navegados serão carregados da rede e se falhar serão retornados do cache para a página na qual o worker.responsive e o worker.online estiverem setados como false;
  • \n
\n

Estratégia de geração de site estático

    \n
  • Requisições de diferentes origens serão realizadas normalmente;
  • \n
  • Requisições diferentes do método GET serão realizadas normalmente;
  • \n
  • Assets com Fingerprints serão carregados no cache no momento da instalação;
  • \n
  • Assets com Fingerprints serão carregados do cache primeiro, e só então retornados para a rede, se necessário;
  • \n
  • Caminhos com uma extensão serão recuperaados e atualizarão o cache em segundo plano para uma requisição subsequente;
  • \n
  • A página inicial será carregada na rede primeiro, e se necessário será retornada uma cópia em cache;
  • \n
  • Caminhos navegados irão carregar apenas os dados da API estática e mesclar com o template da aplicação para gerar a resposta.
  • \n
  • Navegar para uma rota estática irá fazer cache apenas dos dados daquela página;
  • \n
  • Quando os dados estiverem indisponíveis no cache ou na rede irá retornar uma página na qual worker.responsive e worker.online estiverem setados como false;
  • \n
\n

Estratégia customizada

O Nullstack irá instalar automaticamente seu service worker se enabled estiver setado como true com os seguintes eventos:

\n
    \n
  • install
  • \n
  • activate
  • \n
  • fetch
  • \n
\n

Você pode sobreescrever qualquer um desses eventos criando um service-worker.js na pasta public;

\n

Se qualquer uma das palavras chaves acima for encontrada o Nullstack injetará sua função no código do service worker ao invés do padrão.

\n

Por conveniência uma chave chamada context é injetada no self do service worker com as seguintes chaves:

\n\n
function activate(event) {\n  event.waitUntil(async function() {\n    const cacheNames = await caches.keys();\n    const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key);\n    await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName)));\n    if (self.registration.navigationPreload) {\n      await self.registration.navigationPreload.enable();\n    }\n    self.clients.claim();\n  }());\n}\n\nself.addEventListener('activate', activate);\n
\n
\n

💡 O exemplo acima foi extraido do service worker gerado e usa self.context.enviroment.key

\n
\n

Próximo passo

⚔ Aprenda Como fazer o deploy de uma aplicação Nullstack.

\n","description":"O objeto worker é um proxy no Contexto Nullstack disponível em ambos client e server e te dá controle granular do comportamento do seu PWA"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Contexto Service Worker - Nullstack","description":"O objeto worker é um proxy no Contexto Nullstack disponível em ambos client e server e te dá controle granular do comportamento do seu PWA"}} \ No newline at end of file diff --git a/docs/pt-br/sobre.html b/docs/pt-br/sobre.html deleted file mode 100644 index 42cdae49..00000000 --- a/docs/pt-br/sobre.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - Por quê criamos o Nullstack? - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Por quê criamos o Nullstack?

Ele foi criado tendo em mente os programadores acostumados a desenvolver sistemas inteiros sozinhos, mas é facilmente escalável para equipes pequenas ou mesmo grandes, desde que cada programador conheça o fluxo do recurso que deve desenvolver.

-

A Stack

Com a maioria das tecnologias usadas na web hoje em dia, o fluxo mais comum é algo assim:

-
    -
  • Front-end usa um redutor sobre um contexto que chama um fetcher;
  • -
  • Este fetcher traz informações genéricas sobre uma API RESTful;
  • -
  • A API RESTful chama uma rota do servidor, que em seguida chama um controlador, que leva a informação de um modelo e o transforma em um serializer;
  • -
  • Se você precisar de mais de um recurso, este processo deve ser repetido até que todos os recursos sejam buscados;
  • -
  • Depois que todos os dados forem buscados, só então o front-end poderá usá-los;
  • -
  • Raciocinar sobre como lidar como o servidor processará e realizará as etapas acima;
  • -
-

Note que tudo que você queria era mostrar algo a partir do banco de dados em uma visualização. Com o Nullstack, você só precisa se preocupar com a lógica. Todo o resto é Glue Code e o framework deve cuidar disso para você.

-

Feature-driven

Se você está acostumado a trabalhar em mais de um projeto ao mesmo tempo ou mesmo se por acaso tiver que dar manutenção esporádica em muitos de seus projetos antigos, você pode ter tropeçado neste cenário: você não se lembra exatamente onde em seu código está a lógica que você está tentando consertar ou melhorar.

-

Você pode ter um gancho cujas dependências são variáveis locais inicializadas com um estado redux, que foi armazenado em algum ponto por uma ação declarada em algum lugar em seu código fonte e chamada sabe-se lá onde.

-

Se tudo o que pertence a um único recurso estivesse no mesmo arquivo, talvez você não precisasse fazer engenharia reversa em seu próprio código toda vez que precisar atualizar ou corrigir algo.

-

Colocar tudo em um único arquivo pode parecer confuso à primeira vista, mas lembre-se de que você é quem decide a granularidade dessa divisão.

-

Um "recurso" pode ser um formulário de registro inteiro ou algo tão pequeno quanto um botão que faz algumas verificações antes de permitir que você envie esse formulário. Depende inteiramente de você e, como cada componente é tão completo quanto um recurso inteiro, você pode chamar esse botão ou até mesmo o formulário inteiro em outras páginas de seu aplicativo. Isso nos leva à Verdadeira componentização e reutilização de código.

-

Componentização e reutilização de código

Os componentes do Nullstack são autossuficientes.

-

A maioria dos frameworks são especializados em apenas uma camada do desenvolvimento. Ao exportar um componente Nullstack, todo o código necessário para rodar o recurso vai ficar junto, sem a necessidade de alocar as outras camadas separadamente.

-

Como efeito colateral, aplicativos inteiros podem ser usados como componentes e montados em outros aplicativos como engines.

-

Por quê usar Orientação à objetos e não componentes funcionais

À primeira vista, as classes podem parecer mais detalhadas do que os componentes funcionais. -Esta seção explicará os motivos que nos levam a favorecer as classes no desenvolvimento do Nullstack.

-

As razões estão, na verdade, conectadas a alguns princípios básicos do Nullstack, sendo:

-

Tudo é possivel

Nós não queremos introduzir um “modo Nullstack” de fazer as coisas, queremos que se torne algo acessível a qualquer pessoa com algum conhecimento Javascript.

-

Dito isso, o primeiro grande problema foi abordar o gerenciamento de estado de uma forma Javascript padrão. O suporte de componentes funcionais exigiria uma solução semelhante aos ganchos de React.js, que seriam considerados um maneirismo do framework.

-

Uma vez que optamos pela imutabilidade como uma restrição do framework, podemos usar a forma nativa de definir variáveis simples. Isto remove a complexidade do gerenciamento de estados, o que foi responsável anteriormente pela necessidade de usar uma biblioteca de terceiros para o gerenciamento dos mesmos

-

Nenhum Glue Code ou “baterias incluídas”

O Nullstack pega emprestado o conceito de “bateria incluída” do Ember.js, mas permite que você troque as baterias. Tudo que você precisa para fazer um aplicativo deve fazer parte do framework e ainda ser flexível.

-

O framework deve fazer o trabalho pesado e o programador deveria focar na sua própria aplicação. -Por esse motivo tudo que você precisa fazer é declarar suas classes e deixar que o Nullstack instancie elas para você. -Desta forma, nos removemos o aspecto mais doloroso de lidar com classes enquanto mantemos todas as vantagens delas.

-

Rota de fuga segura

Orientado a objetos vs. funcional não é um tópico novo e, ultimamente, o primeiro parece ter sido excluído da maioria dos frameworks, não deixando lugar para desenvolvedores que gostam desse padrão.

-

É certo que as classes demoraram muito para serem padronizadas em Javascript e o atraso pode ter causado algumas implementações traumáticas ao longo do caminho.

-

Embora a programação orientada a objetos possa não ser a melhor solução para todos os problemas, o Nullstack permite que você importe funções livremente e as use nos momentos em que você achar melhor.

-

Por que injeção de dependência em vez de modularidade

O contexto do Nullstack usa o padrão de injeção de dependência, o que significa que tudo o que você precisa pode ser solicitado do framework a partir da camada em que está a função.

-

O contexto é um objeto com escopo horizontal que é injetado em todas as suas chamadas de função. A natureza não hierárquica desse padrão permite que você mova facilmente a lógica de seu componente conforme seu aplicativo cresce, enquanto ainda evita problemas com threading ou encher seu código-fonte com inúmeras declarações para a mesma coisa.

-

Isso tem duas vantagens principais:

-
    -
  • Você vê as dependências de seu código em uma função, em vez de tê-los todos importados na parte superior do arquivo.

  • -
  • O framework é capaz de lhe dar informações mais precisas sobre o ambiente específico para essa chamada de função.

  • -
-

Felicidade do desenvolvedor

A aplicação gerada é suficiente para ser um PWA (Progressive Web App) sem pensar em boilerplates, e ainda mais, você é livre para substituir o comportamento padrão das funções.

-

Um conceito emprestado do Ruby é a “felicidade do desenvolvedor”. O objetivo do Nullstack é facilitar a vida do desenvolvedor, simplificando tudo o que for possível sem esconder nada de você.

-

Os primeiros desenvolvedores que queríamos deixar felizes somos nós mesmos. Fizemos o Nullstack porque nos divertimos no processo. Tudo começou como um protótipo simples em cima do React.js e nos empolgamos, tornando-o cada vez mais agradável para nós até que se tornou algo próprio.

-

Esperamos que você goste de usar o Nullstack tanto quanto nós, porque é isso que mantém este projeto avançando.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/sobre/index.html b/docs/pt-br/sobre/index.html deleted file mode 100644 index 42cdae49..00000000 --- a/docs/pt-br/sobre/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - Por quê criamos o Nullstack? - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Por quê criamos o Nullstack?

Ele foi criado tendo em mente os programadores acostumados a desenvolver sistemas inteiros sozinhos, mas é facilmente escalável para equipes pequenas ou mesmo grandes, desde que cada programador conheça o fluxo do recurso que deve desenvolver.

-

A Stack

Com a maioria das tecnologias usadas na web hoje em dia, o fluxo mais comum é algo assim:

-
    -
  • Front-end usa um redutor sobre um contexto que chama um fetcher;
  • -
  • Este fetcher traz informações genéricas sobre uma API RESTful;
  • -
  • A API RESTful chama uma rota do servidor, que em seguida chama um controlador, que leva a informação de um modelo e o transforma em um serializer;
  • -
  • Se você precisar de mais de um recurso, este processo deve ser repetido até que todos os recursos sejam buscados;
  • -
  • Depois que todos os dados forem buscados, só então o front-end poderá usá-los;
  • -
  • Raciocinar sobre como lidar como o servidor processará e realizará as etapas acima;
  • -
-

Note que tudo que você queria era mostrar algo a partir do banco de dados em uma visualização. Com o Nullstack, você só precisa se preocupar com a lógica. Todo o resto é Glue Code e o framework deve cuidar disso para você.

-

Feature-driven

Se você está acostumado a trabalhar em mais de um projeto ao mesmo tempo ou mesmo se por acaso tiver que dar manutenção esporádica em muitos de seus projetos antigos, você pode ter tropeçado neste cenário: você não se lembra exatamente onde em seu código está a lógica que você está tentando consertar ou melhorar.

-

Você pode ter um gancho cujas dependências são variáveis locais inicializadas com um estado redux, que foi armazenado em algum ponto por uma ação declarada em algum lugar em seu código fonte e chamada sabe-se lá onde.

-

Se tudo o que pertence a um único recurso estivesse no mesmo arquivo, talvez você não precisasse fazer engenharia reversa em seu próprio código toda vez que precisar atualizar ou corrigir algo.

-

Colocar tudo em um único arquivo pode parecer confuso à primeira vista, mas lembre-se de que você é quem decide a granularidade dessa divisão.

-

Um "recurso" pode ser um formulário de registro inteiro ou algo tão pequeno quanto um botão que faz algumas verificações antes de permitir que você envie esse formulário. Depende inteiramente de você e, como cada componente é tão completo quanto um recurso inteiro, você pode chamar esse botão ou até mesmo o formulário inteiro em outras páginas de seu aplicativo. Isso nos leva à Verdadeira componentização e reutilização de código.

-

Componentização e reutilização de código

Os componentes do Nullstack são autossuficientes.

-

A maioria dos frameworks são especializados em apenas uma camada do desenvolvimento. Ao exportar um componente Nullstack, todo o código necessário para rodar o recurso vai ficar junto, sem a necessidade de alocar as outras camadas separadamente.

-

Como efeito colateral, aplicativos inteiros podem ser usados como componentes e montados em outros aplicativos como engines.

-

Por quê usar Orientação à objetos e não componentes funcionais

À primeira vista, as classes podem parecer mais detalhadas do que os componentes funcionais. -Esta seção explicará os motivos que nos levam a favorecer as classes no desenvolvimento do Nullstack.

-

As razões estão, na verdade, conectadas a alguns princípios básicos do Nullstack, sendo:

-

Tudo é possivel

Nós não queremos introduzir um “modo Nullstack” de fazer as coisas, queremos que se torne algo acessível a qualquer pessoa com algum conhecimento Javascript.

-

Dito isso, o primeiro grande problema foi abordar o gerenciamento de estado de uma forma Javascript padrão. O suporte de componentes funcionais exigiria uma solução semelhante aos ganchos de React.js, que seriam considerados um maneirismo do framework.

-

Uma vez que optamos pela imutabilidade como uma restrição do framework, podemos usar a forma nativa de definir variáveis simples. Isto remove a complexidade do gerenciamento de estados, o que foi responsável anteriormente pela necessidade de usar uma biblioteca de terceiros para o gerenciamento dos mesmos

-

Nenhum Glue Code ou “baterias incluídas”

O Nullstack pega emprestado o conceito de “bateria incluída” do Ember.js, mas permite que você troque as baterias. Tudo que você precisa para fazer um aplicativo deve fazer parte do framework e ainda ser flexível.

-

O framework deve fazer o trabalho pesado e o programador deveria focar na sua própria aplicação. -Por esse motivo tudo que você precisa fazer é declarar suas classes e deixar que o Nullstack instancie elas para você. -Desta forma, nos removemos o aspecto mais doloroso de lidar com classes enquanto mantemos todas as vantagens delas.

-

Rota de fuga segura

Orientado a objetos vs. funcional não é um tópico novo e, ultimamente, o primeiro parece ter sido excluído da maioria dos frameworks, não deixando lugar para desenvolvedores que gostam desse padrão.

-

É certo que as classes demoraram muito para serem padronizadas em Javascript e o atraso pode ter causado algumas implementações traumáticas ao longo do caminho.

-

Embora a programação orientada a objetos possa não ser a melhor solução para todos os problemas, o Nullstack permite que você importe funções livremente e as use nos momentos em que você achar melhor.

-

Por que injeção de dependência em vez de modularidade

O contexto do Nullstack usa o padrão de injeção de dependência, o que significa que tudo o que você precisa pode ser solicitado do framework a partir da camada em que está a função.

-

O contexto é um objeto com escopo horizontal que é injetado em todas as suas chamadas de função. A natureza não hierárquica desse padrão permite que você mova facilmente a lógica de seu componente conforme seu aplicativo cresce, enquanto ainda evita problemas com threading ou encher seu código-fonte com inúmeras declarações para a mesma coisa.

-

Isso tem duas vantagens principais:

-
    -
  • Você vê as dependências de seu código em uma função, em vez de tê-los todos importados na parte superior do arquivo.

  • -
  • O framework é capaz de lhe dar informações mais precisas sobre o ambiente específico para essa chamada de função.

  • -
-

Felicidade do desenvolvedor

A aplicação gerada é suficiente para ser um PWA (Progressive Web App) sem pensar em boilerplates, e ainda mais, você é livre para substituir o comportamento padrão das funções.

-

Um conceito emprestado do Ruby é a “felicidade do desenvolvedor”. O objetivo do Nullstack é facilitar a vida do desenvolvedor, simplificando tudo o que for possível sem esconder nada de você.

-

Os primeiros desenvolvedores que queríamos deixar felizes somos nós mesmos. Fizemos o Nullstack porque nos divertimos no processo. Tudo começou como um protótipo simples em cima do React.js e nos empolgamos, tornando-o cada vez mais agradável para nós até que se tornou algo próprio.

-

Esperamos que você goste de usar o Nullstack tanto quanto nós, porque é isso que mantém este projeto avançando.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/sobre/index.json b/docs/pt-br/sobre/index.json deleted file mode 100644 index 8991b7f5..00000000 --- a/docs/pt-br/sobre/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Por quê criamos o Nullstack?","html":"

Ele foi criado tendo em mente os programadores acostumados a desenvolver sistemas inteiros sozinhos, mas é facilmente escalável para equipes pequenas ou mesmo grandes, desde que cada programador conheça o fluxo do recurso que deve desenvolver.

\n

A Stack

Com a maioria das tecnologias usadas na web hoje em dia, o fluxo mais comum é algo assim:

\n
    \n
  • Front-end usa um redutor sobre um contexto que chama um fetcher;
  • \n
  • Este fetcher traz informações genéricas sobre uma API RESTful;
  • \n
  • A API RESTful chama uma rota do servidor, que em seguida chama um controlador, que leva a informação de um modelo e o transforma em um serializer;
  • \n
  • Se você precisar de mais de um recurso, este processo deve ser repetido até que todos os recursos sejam buscados;
  • \n
  • Depois que todos os dados forem buscados, só então o front-end poderá usá-los;
  • \n
  • Raciocinar sobre como lidar como o servidor processará e realizará as etapas acima;
  • \n
\n

Note que tudo que você queria era mostrar algo a partir do banco de dados em uma visualização. Com o Nullstack, você só precisa se preocupar com a lógica. Todo o resto é Glue Code e o framework deve cuidar disso para você.

\n

Feature-driven

Se você está acostumado a trabalhar em mais de um projeto ao mesmo tempo ou mesmo se por acaso tiver que dar manutenção esporádica em muitos de seus projetos antigos, você pode ter tropeçado neste cenário: você não se lembra exatamente onde em seu código está a lógica que você está tentando consertar ou melhorar.

\n

Você pode ter um gancho cujas dependências são variáveis locais inicializadas com um estado redux, que foi armazenado em algum ponto por uma ação declarada em algum lugar em seu código fonte e chamada sabe-se lá onde.

\n

Se tudo o que pertence a um único recurso estivesse no mesmo arquivo, talvez você não precisasse fazer engenharia reversa em seu próprio código toda vez que precisar atualizar ou corrigir algo.

\n

Colocar tudo em um único arquivo pode parecer confuso à primeira vista, mas lembre-se de que você é quem decide a granularidade dessa divisão.

\n

Um "recurso" pode ser um formulário de registro inteiro ou algo tão pequeno quanto um botão que faz algumas verificações antes de permitir que você envie esse formulário. Depende inteiramente de você e, como cada componente é tão completo quanto um recurso inteiro, você pode chamar esse botão ou até mesmo o formulário inteiro em outras páginas de seu aplicativo. Isso nos leva à Verdadeira componentização e reutilização de código.

\n

Componentização e reutilização de código

Os componentes do Nullstack são autossuficientes.

\n

A maioria dos frameworks são especializados em apenas uma camada do desenvolvimento. Ao exportar um componente Nullstack, todo o código necessário para rodar o recurso vai ficar junto, sem a necessidade de alocar as outras camadas separadamente.

\n

Como efeito colateral, aplicativos inteiros podem ser usados como componentes e montados em outros aplicativos como engines.

\n

Por quê usar Orientação à objetos e não componentes funcionais

À primeira vista, as classes podem parecer mais detalhadas do que os componentes funcionais.\nEsta seção explicará os motivos que nos levam a favorecer as classes no desenvolvimento do Nullstack.

\n

As razões estão, na verdade, conectadas a alguns princípios básicos do Nullstack, sendo:

\n

Tudo é possivel

Nós não queremos introduzir um “modo Nullstack” de fazer as coisas, queremos que se torne algo acessível a qualquer pessoa com algum conhecimento Javascript.

\n

Dito isso, o primeiro grande problema foi abordar o gerenciamento de estado de uma forma Javascript padrão. O suporte de componentes funcionais exigiria uma solução semelhante aos ganchos de React.js, que seriam considerados um maneirismo do framework.

\n

Uma vez que optamos pela imutabilidade como uma restrição do framework, podemos usar a forma nativa de definir variáveis simples. Isto remove a complexidade do gerenciamento de estados, o que foi responsável anteriormente pela necessidade de usar uma biblioteca de terceiros para o gerenciamento dos mesmos

\n

Nenhum Glue Code ou “baterias incluídas”

O Nullstack pega emprestado o conceito de “bateria incluída” do Ember.js, mas permite que você troque as baterias. Tudo que você precisa para fazer um aplicativo deve fazer parte do framework e ainda ser flexível.

\n

O framework deve fazer o trabalho pesado e o programador deveria focar na sua própria aplicação.\nPor esse motivo tudo que você precisa fazer é declarar suas classes e deixar que o Nullstack instancie elas para você.\nDesta forma, nos removemos o aspecto mais doloroso de lidar com classes enquanto mantemos todas as vantagens delas.

\n

Rota de fuga segura

Orientado a objetos vs. funcional não é um tópico novo e, ultimamente, o primeiro parece ter sido excluído da maioria dos frameworks, não deixando lugar para desenvolvedores que gostam desse padrão.

\n

É certo que as classes demoraram muito para serem padronizadas em Javascript e o atraso pode ter causado algumas implementações traumáticas ao longo do caminho.

\n

Embora a programação orientada a objetos possa não ser a melhor solução para todos os problemas, o Nullstack permite que você importe funções livremente e as use nos momentos em que você achar melhor.

\n

Por que injeção de dependência em vez de modularidade

O contexto do Nullstack usa o padrão de injeção de dependência, o que significa que tudo o que você precisa pode ser solicitado do framework a partir da camada em que está a função.

\n

O contexto é um objeto com escopo horizontal que é injetado em todas as suas chamadas de função. A natureza não hierárquica desse padrão permite que você mova facilmente a lógica de seu componente conforme seu aplicativo cresce, enquanto ainda evita problemas com threading ou encher seu código-fonte com inúmeras declarações para a mesma coisa.

\n

Isso tem duas vantagens principais:

\n
    \n
  • Você vê as dependências de seu código em uma função, em vez de tê-los todos importados na parte superior do arquivo.

  • \n
  • O framework é capaz de lhe dar informações mais precisas sobre o ambiente específico para essa chamada de função.

  • \n
\n

Felicidade do desenvolvedor

A aplicação gerada é suficiente para ser um PWA (Progressive Web App) sem pensar em boilerplates, e ainda mais, você é livre para substituir o comportamento padrão das funções.

\n

Um conceito emprestado do Ruby é a “felicidade do desenvolvedor”. O objetivo do Nullstack é facilitar a vida do desenvolvedor, simplificando tudo o que for possível sem esconder nada de você.

\n

Os primeiros desenvolvedores que queríamos deixar felizes somos nós mesmos. Fizemos o Nullstack porque nos divertimos no processo. Tudo começou como um protótipo simples em cima do React.js e nos empolgamos, tornando-o cada vez mais agradável para nós até que se tornou algo próprio.

\n

Esperamos que você goste de usar o Nullstack tanto quanto nós, porque é isso que mantém este projeto avançando.

\n","description":"O único propósito de Nullstack é simplificar o desenvolvimento, eliminando o Glue Code e permitindo-lhe se concentrar na lógica de sua aplicação."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Por quê criamos o Nullstack? - Nullstack","description":"O único propósito de Nullstack é simplificar o desenvolvimento, eliminando o Glue Code e permitindo-lhe se concentrar na lógica de sua aplicação."}} \ No newline at end of file diff --git "a/docs/pt-br/trabalhador-servi\303\247o.html" "b/docs/pt-br/trabalhador-servi\303\247o.html" deleted file mode 100644 index e64e45b7..00000000 --- "a/docs/pt-br/trabalhador-servi\303\247o.html" +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Página Não Encontrada - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Página Não Encontrada

- - - \ No newline at end of file diff --git "a/docs/pt-br/trabalhador-servi\303\247o/index.html" "b/docs/pt-br/trabalhador-servi\303\247o/index.html" deleted file mode 100644 index e64e45b7..00000000 --- "a/docs/pt-br/trabalhador-servi\303\247o/index.html" +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Página Não Encontrada - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Página Não Encontrada

- - - \ No newline at end of file diff --git "a/docs/pt-br/trabalhador-servi\303\247o/index.json" "b/docs/pt-br/trabalhador-servi\303\247o/index.json" deleted file mode 100644 index b918fadd..00000000 --- "a/docs/pt-br/trabalhador-servi\303\247o/index.json" +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Página Não Encontrada","html":"

Talvez você queira aprender como criar uma pagina 404 com Nullstack?

\n

Se você está procurando por outra coisa, você deveria ler a documentação.

\n","description":"Desculpe, essa não é a página que você está procurando","status":404},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":404,"title":"Página Não Encontrada - Nullstack","description":"Desculpe, essa não é a página que você está procurando"}} \ No newline at end of file diff --git a/docs/pt-br/vinculo-bidirecional.html b/docs/pt-br/vinculo-bidirecional.html deleted file mode 100644 index 4366e725..00000000 --- a/docs/pt-br/vinculo-bidirecional.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - Two-Way Binding - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Two-Way Binding

Big chunks of code in a progressive web application is dedicated to reacting to user input.

-

The process of controlling user input can be broken into 3 tedious steps:

-
    -
  • Declaring a variable with the initial value;
  • -
  • Passing the initial value to the input;
  • -
  • Observing changes in the input and assigning the new value to the variable.
  • -
-

The last step might include typecasting and other value treatments.

-

This process in which you manually do all these steps is called one-way binding, it is the default in many frameworks, and is possible in Nullstack.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
-
-  updateString({event}) {
-    this.string = event.target.value;
-  }
-
-  updateNumber({event}) {
-    this.number = parseInt(event.target.value);
-  }
- 
-  render() {
-    return (
-      <form>
-        <input
-          type="text"
-          name="string"
-          value={this.string}
-          oninput={this.updateString}
-        />
-        <input
-          type="number"
-          name="number"
-          value={this.number}
-          oninput={this.updateNumber}
-        />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

The bind attribute

Bind reduces drastically the amount of glue code you have to type in your application.

-

You can shortcut setting a value, name, and event with the bind attribute.

-
-

💡 Nullstack will simply replace bind with the value, name, and event under the hood.

-
-

Bind will generate an event that automatically typecasts to the previous primitive type the value was.

-

You can pass any variable to the bind as long as its parent object is mentioned.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
- 
-  render() {
-    return (
-      <form>
-        <input type="text" bind={this.string} />
-        <input type="number" bind={this.number} />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

Bound Events

The following events are set for each type of input:

-
    -
  • onclick for inputs with the checkbox type
  • -
  • oninput for other inputs and textareas
  • -
  • onchange for anything else
  • -
-

You can still declare an attribute with the same bound event.

-

Events will not override the bound event, instead, it will be executed after bind mutates the variable.

-

The new value will be merged into the function context.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  name = '';
-
-  compare({value}) {
-    this.name === value;
-  }
- 
-  render() {
-    return (
-      <input bind={this.name} oninput={this.compare} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Bind source

Bind can take a source attribute as well.

-
-

💡 If you do not declare a source to the bind, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

-
-

If you declare a source, bind must be a string with the name of the key that will be mutated.

-

The source will be merged into the context of events.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  validate({source, params}) {
-    if(!source.page) {
-      params.page = '1';
-    }
-  }
-
-  render({params}) {
-    return (
-      <input 
-        source={params}
-        bind="page"
-        oninput={this.validate}
-      />
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

💡 Binding by reference is possible because all binds are converted to the format above at transpile time.

-
-

Any object that responds to a key call with "[]" can be bound.

-

The name attribute can be overwritten.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  character = 'a';
-  text = 'aaaa';
-  
-  object = {count: 1};
-  array = ['a', 'b', 'c'];
-
-  render({params}) {
-    return (
-      <div>
-        <input bind={this.number} />
-        <textarea bind={this.text} />
-        <select bind={this.character}>
-          {this.array.map((character) => <option>{character}</option>)}
-        </select>
-        <select bind={this.boolean} name="boolean-select">
-          <option value={true}>true</option>
-          <option value={false}>false</option>
-        </select>
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.count} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </div>
-    )
-  }
-
-}
-
-export default Form;
-
-

Object Events

You can use object events alongside bind normally.

-

The event will run after the variable is mutated.

-

The event will share the bind source.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  render({params}) {
-    return (
-      <input bind={params.filter} oninput={{page: 1}} />
-    )
-  }
-
-}
-
-export default Paginator;
-
-

Bindable Components

You can create your own bindable component by receiving the attributes that bind generates.

-

You must respond by calling onchange with a value key.

-

You can also merge any other keys you wish to send to the component user.

-
class CurrencyInput extends Nullstack {
-
-  parse({event, onchange}) {
-    const normalized = event.target.value.replace(',', '').padStart(3, '0');
-    const whole = (parseInt(normalized.slice(0,-2)) || 0).toString();
-    const decimal = normalized.slice(normalized.length - 2);
-    const value = parseFloat(whole+'.'+decimal);
-    const bringsHappyness = value >= 1000000;
-    onchange({value, bringsHappyness});
-  }
-
-  render({value, name}) {
-    const formatted = value.toFixed(2).replace('.', ',');
-    return <input name={name} value={formatted} oninput={this.parse} />
-  }
-
-}
-
-
import Nullstack from 'nullstack';
-import CurrencyInput from './CurrencyInput';
-
-class Form extends Nullstack {
-
-  balance = 0;
-
-  render() {
-    return (
-      <CurrencyInput bind={this.balance} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Next step

-

🎉 Congratulations!. You are done with the core concepts!

-
-

⚔ Learn about the application startup.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/vinculo-bidirecional/index.html b/docs/pt-br/vinculo-bidirecional/index.html deleted file mode 100644 index 4366e725..00000000 --- a/docs/pt-br/vinculo-bidirecional/index.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - Two-Way Binding - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Two-Way Binding

Big chunks of code in a progressive web application is dedicated to reacting to user input.

-

The process of controlling user input can be broken into 3 tedious steps:

-
    -
  • Declaring a variable with the initial value;
  • -
  • Passing the initial value to the input;
  • -
  • Observing changes in the input and assigning the new value to the variable.
  • -
-

The last step might include typecasting and other value treatments.

-

This process in which you manually do all these steps is called one-way binding, it is the default in many frameworks, and is possible in Nullstack.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
-
-  updateString({event}) {
-    this.string = event.target.value;
-  }
-
-  updateNumber({event}) {
-    this.number = parseInt(event.target.value);
-  }
- 
-  render() {
-    return (
-      <form>
-        <input
-          type="text"
-          name="string"
-          value={this.string}
-          oninput={this.updateString}
-        />
-        <input
-          type="number"
-          name="number"
-          value={this.number}
-          oninput={this.updateNumber}
-        />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

The bind attribute

Bind reduces drastically the amount of glue code you have to type in your application.

-

You can shortcut setting a value, name, and event with the bind attribute.

-
-

💡 Nullstack will simply replace bind with the value, name, and event under the hood.

-
-

Bind will generate an event that automatically typecasts to the previous primitive type the value was.

-

You can pass any variable to the bind as long as its parent object is mentioned.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
- 
-  render() {
-    return (
-      <form>
-        <input type="text" bind={this.string} />
-        <input type="number" bind={this.number} />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

Bound Events

The following events are set for each type of input:

-
    -
  • onclick for inputs with the checkbox type
  • -
  • oninput for other inputs and textareas
  • -
  • onchange for anything else
  • -
-

You can still declare an attribute with the same bound event.

-

Events will not override the bound event, instead, it will be executed after bind mutates the variable.

-

The new value will be merged into the function context.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  name = '';
-
-  compare({value}) {
-    this.name === value;
-  }
- 
-  render() {
-    return (
-      <input bind={this.name} oninput={this.compare} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Bind source

Bind can take a source attribute as well.

-
-

💡 If you do not declare a source to the bind, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

-
-

If you declare a source, bind must be a string with the name of the key that will be mutated.

-

The source will be merged into the context of events.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  validate({source, params}) {
-    if(!source.page) {
-      params.page = '1';
-    }
-  }
-
-  render({params}) {
-    return (
-      <input 
-        source={params}
-        bind="page"
-        oninput={this.validate}
-      />
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

💡 Binding by reference is possible because all binds are converted to the format above at transpile time.

-
-

Any object that responds to a key call with "[]" can be bound.

-

The name attribute can be overwritten.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  character = 'a';
-  text = 'aaaa';
-  
-  object = {count: 1};
-  array = ['a', 'b', 'c'];
-
-  render({params}) {
-    return (
-      <div>
-        <input bind={this.number} />
-        <textarea bind={this.text} />
-        <select bind={this.character}>
-          {this.array.map((character) => <option>{character}</option>)}
-        </select>
-        <select bind={this.boolean} name="boolean-select">
-          <option value={true}>true</option>
-          <option value={false}>false</option>
-        </select>
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.count} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </div>
-    )
-  }
-
-}
-
-export default Form;
-
-

Object Events

You can use object events alongside bind normally.

-

The event will run after the variable is mutated.

-

The event will share the bind source.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  render({params}) {
-    return (
-      <input bind={params.filter} oninput={{page: 1}} />
-    )
-  }
-
-}
-
-export default Paginator;
-
-

Bindable Components

You can create your own bindable component by receiving the attributes that bind generates.

-

You must respond by calling onchange with a value key.

-

You can also merge any other keys you wish to send to the component user.

-
class CurrencyInput extends Nullstack {
-
-  parse({event, onchange}) {
-    const normalized = event.target.value.replace(',', '').padStart(3, '0');
-    const whole = (parseInt(normalized.slice(0,-2)) || 0).toString();
-    const decimal = normalized.slice(normalized.length - 2);
-    const value = parseFloat(whole+'.'+decimal);
-    const bringsHappyness = value >= 1000000;
-    onchange({value, bringsHappyness});
-  }
-
-  render({value, name}) {
-    const formatted = value.toFixed(2).replace('.', ',');
-    return <input name={name} value={formatted} oninput={this.parse} />
-  }
-
-}
-
-
import Nullstack from 'nullstack';
-import CurrencyInput from './CurrencyInput';
-
-class Form extends Nullstack {
-
-  balance = 0;
-
-  render() {
-    return (
-      <CurrencyInput bind={this.balance} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Next step

-

🎉 Congratulations!. You are done with the core concepts!

-
-

⚔ Learn about the application startup.

-
- - - \ No newline at end of file diff --git a/docs/pt-br/vinculo-bidirecional/index.json b/docs/pt-br/vinculo-bidirecional/index.json deleted file mode 100644 index 7e87822a..00000000 --- a/docs/pt-br/vinculo-bidirecional/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-11":{"title":"Two-Way Binding","html":"

Big chunks of code in a progressive web application is dedicated to reacting to user input.

\n

The process of controlling user input can be broken into 3 tedious steps:

\n
    \n
  • Declaring a variable with the initial value;
  • \n
  • Passing the initial value to the input;
  • \n
  • Observing changes in the input and assigning the new value to the variable.
  • \n
\n

The last step might include typecasting and other value treatments.

\n

This process in which you manually do all these steps is called one-way binding, it is the default in many frameworks, and is possible in Nullstack.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  number = 1;\n  string = '';\n\n  updateString({event}) {\n    this.string = event.target.value;\n  }\n\n  updateNumber({event}) {\n    this.number = parseInt(event.target.value);\n  }\n \n  render() {\n    return (\n      <form>\n        <input\n          type=\"text\"\n          name=\"string\"\n          value={this.string}\n          oninput={this.updateString}\n        />\n        <input\n          type=\"number\"\n          name=\"number\"\n          value={this.number}\n          oninput={this.updateNumber}\n        />\n      </form>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

The bind attribute

Bind reduces drastically the amount of glue code you have to type in your application.

\n

You can shortcut setting a value, name, and event with the bind attribute.

\n
\n

💡 Nullstack will simply replace bind with the value, name, and event under the hood.

\n
\n

Bind will generate an event that automatically typecasts to the previous primitive type the value was.

\n

You can pass any variable to the bind as long as its parent object is mentioned.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  number = 1;\n  string = '';\n \n  render() {\n    return (\n      <form>\n        <input type=\"text\" bind={this.string} />\n        <input type=\"number\" bind={this.number} />\n      </form>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Bound Events

The following events are set for each type of input:

\n
    \n
  • onclick for inputs with the checkbox type
  • \n
  • oninput for other inputs and textareas
  • \n
  • onchange for anything else
  • \n
\n

You can still declare an attribute with the same bound event.

\n

Events will not override the bound event, instead, it will be executed after bind mutates the variable.

\n

The new value will be merged into the function context.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  name = '';\n\n  compare({value}) {\n    this.name === value;\n  }\n \n  render() {\n    return (\n      <input bind={this.name} oninput={this.compare} />\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Bind source

Bind can take a source attribute as well.

\n
\n

💡 If you do not declare a source to the bind, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

\n
\n

If you declare a source, bind must be a string with the name of the key that will be mutated.

\n

The source will be merged into the context of events.

\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n\n  validate({source, params}) {\n    if(!source.page) {\n      params.page = '1';\n    }\n  }\n\n  render({params}) {\n    return (\n      <input \n        source={params}\n        bind=\"page\"\n        oninput={this.validate}\n      />\n    )\n  }\n\n}\n\nexport default Paginator;\n
\n
\n

💡 Binding by reference is possible because all binds are converted to the format above at transpile time.

\n
\n

Any object that responds to a key call with "[]" can be bound.

\n

The name attribute can be overwritten.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  number = 1;\n  boolean = true;\n  character = 'a';\n  text = 'aaaa';\n  \n  object = {count: 1};\n  array = ['a', 'b', 'c'];\n\n  render({params}) {\n    return (\n      <div>\n        <input bind={this.number} />\n        <textarea bind={this.text} />\n        <select bind={this.character}>\n          {this.array.map((character) => <option>{character}</option>)}\n        </select>\n        <select bind={this.boolean} name=\"boolean-select\">\n          <option value={true}>true</option>\n          <option value={false}>false</option>\n        </select>\n        <input bind={this.boolean} type=\"checkbox\" />\n        <input bind={this.object.count} />\n        {this.array.map((value, index) => (\n          <input bind={this.array[index]} />\n        ))}\n        <input bind={params.page} />\n      </div>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Object Events

You can use object events alongside bind normally.

\n

The event will run after the variable is mutated.

\n

The event will share the bind source.

\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n\n  render({params}) {\n    return (\n      <input bind={params.filter} oninput={{page: 1}} />\n    )\n  }\n\n}\n\nexport default Paginator;\n
\n

Bindable Components

You can create your own bindable component by receiving the attributes that bind generates.

\n

You must respond by calling onchange with a value key.

\n

You can also merge any other keys you wish to send to the component user.

\n
class CurrencyInput extends Nullstack {\n\n  parse({event, onchange}) {\n    const normalized = event.target.value.replace(',', '').padStart(3, '0');\n    const whole = (parseInt(normalized.slice(0,-2)) || 0).toString();\n    const decimal = normalized.slice(normalized.length - 2);\n    const value = parseFloat(whole+'.'+decimal);\n    const bringsHappyness = value >= 1000000;\n    onchange({value, bringsHappyness});\n  }\n\n  render({value, name}) {\n    const formatted = value.toFixed(2).replace('.', ',');\n    return <input name={name} value={formatted} oninput={this.parse} />\n  }\n\n}\n
\n
import Nullstack from 'nullstack';\nimport CurrencyInput from './CurrencyInput';\n\nclass Form extends Nullstack {\n\n  balance = 0;\n\n  render() {\n    return (\n      <CurrencyInput bind={this.balance} />\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Next step

\n

🎉 Congratulations!. You are done with the core concepts!

\n
\n

⚔ Learn about the application startup.

\n","description":"Bind reduces drastically the amount of glue code you have to type in your application."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Two-Way Binding - Nullstack","description":"Bind reduces drastically the amount of glue code you have to type in your application."}} \ No newline at end of file diff --git a/docs/pt-br/waifu.html b/docs/pt-br/waifu.html deleted file mode 100644 index f781243a..00000000 --- a/docs/pt-br/waifu.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Nulla-Chan - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nulla-Chan

Nulla - Chan

Waifu oficial do Nullstack

  • 🕐 Idade: 19
  • ♒ Signo: Aquário
  • 🎂 Aniversário: 28 de Janeiro
  • 💖 Tipo Sanguíneo: A
  • 📏 Altura: 1,55m
  • 🍨 Comida Favorita: Qualquer coisa com sabor de baunilha
  • 🧩 Hobby: Reinventar Rodas
  • 🧠 Neurodivergências: TDAH e TEA
🎨 Criada por: Bilkaya Confira o Conceito da Personagem

Uma doce e tímida waifu perfeita, está sempre hiperfocada em seus estudos, mas de alguma forma distraída ao mesmo tempo.

Está sempre alegre... até que ela tenha que enfrentar código grudento ou ver um post dizendo que tecnologia ela deve usar.

- - - \ No newline at end of file diff --git a/docs/pt-br/waifu/index.html b/docs/pt-br/waifu/index.html deleted file mode 100644 index f781243a..00000000 --- a/docs/pt-br/waifu/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Nulla-Chan - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nulla-Chan

Nulla - Chan

Waifu oficial do Nullstack

  • 🕐 Idade: 19
  • ♒ Signo: Aquário
  • 🎂 Aniversário: 28 de Janeiro
  • 💖 Tipo Sanguíneo: A
  • 📏 Altura: 1,55m
  • 🍨 Comida Favorita: Qualquer coisa com sabor de baunilha
  • 🧩 Hobby: Reinventar Rodas
  • 🧠 Neurodivergências: TDAH e TEA
🎨 Criada por: Bilkaya Confira o Conceito da Personagem

Uma doce e tímida waifu perfeita, está sempre hiperfocada em seus estudos, mas de alguma forma distraída ao mesmo tempo.

Está sempre alegre... até que ela tenha que enfrentar código grudento ou ver um post dizendo que tecnologia ela deve usar.

- - - \ No newline at end of file diff --git a/docs/pt-br/waifu/index.json b/docs/pt-br/waifu/index.json deleted file mode 100644 index e7243aee..00000000 --- a/docs/pt-br/waifu/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"pt-BR","i18n":{"home":{"title":"Nullstack","href":"/pt-br"},"links":[{"title":"Documentação","href":"/pt-br/documentacao"},{"title":"Componentes","href":"/pt-br/componentes"},{"title":"Contribuidores","href":"/pt-br/contribuidores"},{"title":"Fonte","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"English","href":"/"}],"action":{"title":"Começar","href":"/pt-br/comecando"},"mode":{"dark":"Modo Noite","light":"Modo Dia"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-10":{"locale":"pt-BR","i18n":{"title":"Nulla-Chan","description":"Waifu oficial do Nullstack","tagline":"Waifu oficial do Nullstack","attributes":[{"label":"🕐 Idade","value":"19"},{"label":"♒ Signo","value":"Aquário"},{"label":"🎂 Aniversário","value":"28 de Janeiro"},{"label":"💖 Tipo Sanguíneo","value":"A"},{"label":"📏 Altura","value":"1,55m"},{"label":"🍨 Comida Favorita","value":"Qualquer coisa com sabor de baunilha"},{"label":"🧩 Hobby","value":"Reinventar Rodas"},{"label":"🧠 Neurodivergências","value":"TDAH e TEA"}],"artist":{"label":"🎨 Criada por:","href":"https://www.instagram.com/biancazanette","text":"Bilkaya"},"concept":{"label":"Confira o","href":"https://www.artstation.com/artwork/Vg4o6R","text":"Conceito da Personagem"},"descriptions":["Uma doce e tímida waifu perfeita, está sempre hiperfocada em seus estudos, mas de alguma forma distraída ao mesmo tempo.","Está sempre alegre... até que ela tenha que enfrentar código grudento ou ver um post dizendo que tecnologia ela deve usar."]}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"pt-BR","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Waifu oficial do Nullstack"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Nulla-Chan - Nullstack","description":"Waifu oficial do Nullstack","locale":"pt-BR"}} \ No newline at end of file diff --git a/docs/renderable-components.html b/docs/renderable-components.html deleted file mode 100644 index 967fbc0a..00000000 --- a/docs/renderable-components.html +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - Renderable Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Renderable Components

The simplest component you can make is a renderable component.

-

Renderable components are very similar to web components, they give you the ability to create new HTML tags that shortcut a group of other HTML tags.

-

Create a file in your src folder with the name of your component and the njs extension.

-

In this example it is going to be called HelloWorld.njs.

-

All you have to do is to import Nullstack or any of its subclasses and extend your class from it, define an instance method called render that returns any JSX, and export the component.

-
-

✨ Install the official Nullstack VSCode Extension to generate classes with a snippet.

-
-
import Nullstack from 'nullstack';
-
-class HelloWorld extends Nullstack {
- 
-  render() {
-    return (
-      <div> Hello World </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-

The code above is just declaring the component, you still have to use it.

-

Importing the component in your application gives you the ability to use a new tag in your render.

-

This tag will be replaced with whatever you returned in your component render.

-
import Nullstack from 'nullstack';
-
-import './Application.scss';
-
-import HelloWorld from './HelloWorld';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render({page}) {
-    return (
-      <main>
-        <h1> {page.title} </h1>
-        <a href="https://nullstack.app/documentation" target="_blank"> Read the documentation </a>
-        <HelloWorld />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Using HTML attributes

Nullstack JSX deviates a little from the spec.

-

You can use the normal HTML attributes like class and for directly.

-
<label for="input" class="dont-label-me"> I am a label </label>
-
-

Headless components

If you want to skip rendering the component at all you can simply return false from the render.

-
import Nullstack from 'nullstack';
-
-class Headless extends Nullstack {
- 
-  render() {
-    return false;
-  }
-
-}
-
-export default Headless;
-
-

This will allocate DOM space for when you decide to render markup there.

-

This is also useful for conditional rendering.

-

If all you want to do is to generate an invisible component you can skip defining the render method at all.

-

Inner components

Instead of creating a new component just to organize code-splitting, you can create an inner component.

-

Inner components are any method that the name starts with render followed by an uppercase character.

-

Inner components share the same instance and scope as the main component, therefore, are very convenient to avoid problems like props drilling.

-

To invoke the inner component use a JSX tag with the method name without the render prefix.

-
import Nullstack from 'nullstack';
-
-class Post extends Nullstack {
-
-  renderArticle() {
-    return (
-      <article> Content </article>
-    )
-  }
-
-  renderAside() {
-    return (
-      <aside> Related content </aside>
-    )
-  }
- 
-  render() {
-    return (
-      <div>
-        <Article />
-        <Aside />
-      </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-
-

💡 Nullstack will inject a constant reference to the function at transpile time in order to completely skip the runtime lookup process!

-
-

Boolean attributes

Attributes can be assigned as a boolean.

-

When the value is false the attribute will not be rendered at all.

-

When the value is true it will be rendered as a boolean attribute without a string value.

-
<button disabled={false}> Button </button>
-
-

You can shortcut attributes when you know the value will always be true.

-
<button disabled> Button </button>
-
-
-

✨ Learn more about attributes.

-
-

Element tag

If you need to decide the tag name at runtime, you can use the element tag and set the tag attribute conditionally.

-
<element tag={!!link ? 'a' : 'span'} href={link || false}>
-  some arbitrary text
-</element>
-
-

When the tag attribute is omitted, Nullstack will default to a div.

-

SVG Elements

SVG can be used as if it were any regular HTML tag.

-

You can manipulate the SVG using attributes and events normally.

-
<svg height={this.size} viewBox="0 0 100 100">
-  <circle cx="50" cy="50" r="40" onclick={this.grow} />
-</svg> 
-
-
-

✨ Learn more about events.

-
-

Components with children

Your component can be invoked passing a block of content.

-
<Header> 
-  <h1> Hello World </h1>
-</Header>
-
-

This doesn't automatically render the block since it wouldn't know where to place it.

-

You can destructure the children on the render method and place it in your markup.

-
import Nullstack from 'nullstack';
-
-class Header extends Nullstack {
- 
-  render({children}) {
-    return (
-      <div>{children}</div>
-    )
-  }
-
-}
-
-export default Header;
-
-
-

✨ This is possible because the children key is part of the instance context.

-
-

Lists

You can map over lists without declaring a key.

-

Lists that may change length must be wrapped in a parent element just for them.

-
<ul>
-  {list.map((item) => <li>{item.name}</li>)}
-</ul>
-
-

You can emulate a fixed-size list by returning false instead of an element to reserve dom space.

-
{list.map((item) => (
-  item.visible ? <div>{item.name}</div> : false
-)}
-
-

It's a nice practice to use inner components combined with lists to clean up your code.

-
import Nullstack from 'nullstack';
-
-class List extends Nullstack {
-
-  items = [
-    {visible: true, number: 1},
-    {visible: false, number: 2},
-    {visible: true, number: 3}
-  ]
-
-  renderItem({visible, number}) {
-    if(!visible) return false;
-    return (
-      <li> {number} </li>
-    )
-  }
- 
-  render() {
-    return (
-      <ul>
-        {this.items.map((item) => <Item {...item} />)}
-      </ul>
-    )
-  }
-
-}
-
-export default List;
-
-
-

✨ Sometimes you will notice keys in the map. Learn more about the instance key.

-
-

Inner HTML

You can set the inner HTML of an element with the html attribute.

-

Links inside the HTML string will be replaced with routable anchors.

-
import Nullstack from 'nullstack';
-
-class Post extends Nullstack {
-
-  content = `
-    <h1> This is a Post </h1>
-    <a href="/other-post">
-      Check this other post
-    </a>
-  `;
- 
-  render() {
-    return (
-      <article html={this.content} />
-    )
-  }
-
-}
-
-export default Post;
-
-
-

🔥 Be careful! When using user-generated HTML you are in risk of script injection

-
-

The head tag

Renderable components can render inside the head tag an unlimited number of times at any depth of the application.

-

The head tag will only be updated during the server-side rendering process and changes will be ignored after the hydration process.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <div>
-          <head>
-            <link rel="preconnect" href="https://www.googletagmanager.com" />
-          </head>
-        </div>
-        <head>
-          <link rel="preload" href="/roboto-v20-latin-300.woff2" as="font" type="font/woff2" crossorigin />
-          <link rel="preload" href="/crete-round-v9-latin-regular.woff2" as="font" type="font/woff2" crossorigin />
-        </head>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 You should not use the head tag to update metatags that Nullstack already controls

-
-

Next step

⚔ Add state to your component using stateful components.

-
- - - \ No newline at end of file diff --git a/docs/renderable-components/index.html b/docs/renderable-components/index.html deleted file mode 100644 index 967fbc0a..00000000 --- a/docs/renderable-components/index.html +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - Renderable Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Renderable Components

The simplest component you can make is a renderable component.

-

Renderable components are very similar to web components, they give you the ability to create new HTML tags that shortcut a group of other HTML tags.

-

Create a file in your src folder with the name of your component and the njs extension.

-

In this example it is going to be called HelloWorld.njs.

-

All you have to do is to import Nullstack or any of its subclasses and extend your class from it, define an instance method called render that returns any JSX, and export the component.

-
-

✨ Install the official Nullstack VSCode Extension to generate classes with a snippet.

-
-
import Nullstack from 'nullstack';
-
-class HelloWorld extends Nullstack {
- 
-  render() {
-    return (
-      <div> Hello World </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-

The code above is just declaring the component, you still have to use it.

-

Importing the component in your application gives you the ability to use a new tag in your render.

-

This tag will be replaced with whatever you returned in your component render.

-
import Nullstack from 'nullstack';
-
-import './Application.scss';
-
-import HelloWorld from './HelloWorld';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render({page}) {
-    return (
-      <main>
-        <h1> {page.title} </h1>
-        <a href="https://nullstack.app/documentation" target="_blank"> Read the documentation </a>
-        <HelloWorld />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Using HTML attributes

Nullstack JSX deviates a little from the spec.

-

You can use the normal HTML attributes like class and for directly.

-
<label for="input" class="dont-label-me"> I am a label </label>
-
-

Headless components

If you want to skip rendering the component at all you can simply return false from the render.

-
import Nullstack from 'nullstack';
-
-class Headless extends Nullstack {
- 
-  render() {
-    return false;
-  }
-
-}
-
-export default Headless;
-
-

This will allocate DOM space for when you decide to render markup there.

-

This is also useful for conditional rendering.

-

If all you want to do is to generate an invisible component you can skip defining the render method at all.

-

Inner components

Instead of creating a new component just to organize code-splitting, you can create an inner component.

-

Inner components are any method that the name starts with render followed by an uppercase character.

-

Inner components share the same instance and scope as the main component, therefore, are very convenient to avoid problems like props drilling.

-

To invoke the inner component use a JSX tag with the method name without the render prefix.

-
import Nullstack from 'nullstack';
-
-class Post extends Nullstack {
-
-  renderArticle() {
-    return (
-      <article> Content </article>
-    )
-  }
-
-  renderAside() {
-    return (
-      <aside> Related content </aside>
-    )
-  }
- 
-  render() {
-    return (
-      <div>
-        <Article />
-        <Aside />
-      </div>
-    )
-  }
-
-}
-
-export default HelloWorld;
-
-
-

💡 Nullstack will inject a constant reference to the function at transpile time in order to completely skip the runtime lookup process!

-
-

Boolean attributes

Attributes can be assigned as a boolean.

-

When the value is false the attribute will not be rendered at all.

-

When the value is true it will be rendered as a boolean attribute without a string value.

-
<button disabled={false}> Button </button>
-
-

You can shortcut attributes when you know the value will always be true.

-
<button disabled> Button </button>
-
-
-

✨ Learn more about attributes.

-
-

Element tag

If you need to decide the tag name at runtime, you can use the element tag and set the tag attribute conditionally.

-
<element tag={!!link ? 'a' : 'span'} href={link || false}>
-  some arbitrary text
-</element>
-
-

When the tag attribute is omitted, Nullstack will default to a div.

-

SVG Elements

SVG can be used as if it were any regular HTML tag.

-

You can manipulate the SVG using attributes and events normally.

-
<svg height={this.size} viewBox="0 0 100 100">
-  <circle cx="50" cy="50" r="40" onclick={this.grow} />
-</svg> 
-
-
-

✨ Learn more about events.

-
-

Components with children

Your component can be invoked passing a block of content.

-
<Header> 
-  <h1> Hello World </h1>
-</Header>
-
-

This doesn't automatically render the block since it wouldn't know where to place it.

-

You can destructure the children on the render method and place it in your markup.

-
import Nullstack from 'nullstack';
-
-class Header extends Nullstack {
- 
-  render({children}) {
-    return (
-      <div>{children}</div>
-    )
-  }
-
-}
-
-export default Header;
-
-
-

✨ This is possible because the children key is part of the instance context.

-
-

Lists

You can map over lists without declaring a key.

-

Lists that may change length must be wrapped in a parent element just for them.

-
<ul>
-  {list.map((item) => <li>{item.name}</li>)}
-</ul>
-
-

You can emulate a fixed-size list by returning false instead of an element to reserve dom space.

-
{list.map((item) => (
-  item.visible ? <div>{item.name}</div> : false
-)}
-
-

It's a nice practice to use inner components combined with lists to clean up your code.

-
import Nullstack from 'nullstack';
-
-class List extends Nullstack {
-
-  items = [
-    {visible: true, number: 1},
-    {visible: false, number: 2},
-    {visible: true, number: 3}
-  ]
-
-  renderItem({visible, number}) {
-    if(!visible) return false;
-    return (
-      <li> {number} </li>
-    )
-  }
- 
-  render() {
-    return (
-      <ul>
-        {this.items.map((item) => <Item {...item} />)}
-      </ul>
-    )
-  }
-
-}
-
-export default List;
-
-
-

✨ Sometimes you will notice keys in the map. Learn more about the instance key.

-
-

Inner HTML

You can set the inner HTML of an element with the html attribute.

-

Links inside the HTML string will be replaced with routable anchors.

-
import Nullstack from 'nullstack';
-
-class Post extends Nullstack {
-
-  content = `
-    <h1> This is a Post </h1>
-    <a href="/other-post">
-      Check this other post
-    </a>
-  `;
- 
-  render() {
-    return (
-      <article html={this.content} />
-    )
-  }
-
-}
-
-export default Post;
-
-
-

🔥 Be careful! When using user-generated HTML you are in risk of script injection

-
-

The head tag

Renderable components can render inside the head tag an unlimited number of times at any depth of the application.

-

The head tag will only be updated during the server-side rendering process and changes will be ignored after the hydration process.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  // ...
-
-  render() {
-    return (
-      <main>
-        <div>
-          <head>
-            <link rel="preconnect" href="https://www.googletagmanager.com" />
-          </head>
-        </div>
-        <head>
-          <link rel="preload" href="/roboto-v20-latin-300.woff2" as="font" type="font/woff2" crossorigin />
-          <link rel="preload" href="/crete-round-v9-latin-regular.woff2" as="font" type="font/woff2" crossorigin />
-        </head>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-
-

🔥 You should not use the head tag to update metatags that Nullstack already controls

-
-

Next step

⚔ Add state to your component using stateful components.

-
- - - \ No newline at end of file diff --git a/docs/renderable-components/index.json b/docs/renderable-components/index.json deleted file mode 100644 index 60a07cdf..00000000 --- a/docs/renderable-components/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Renderable Components","html":"

The simplest component you can make is a renderable component.

\n

Renderable components are very similar to web components, they give you the ability to create new HTML tags that shortcut a group of other HTML tags.

\n

Create a file in your src folder with the name of your component and the njs extension.

\n

In this example it is going to be called HelloWorld.njs.

\n

All you have to do is to import Nullstack or any of its subclasses and extend your class from it, define an instance method called render that returns any JSX, and export the component.

\n
\n

✨ Install the official Nullstack VSCode Extension to generate classes with a snippet.

\n
\n
import Nullstack from 'nullstack';\n\nclass HelloWorld extends Nullstack {\n \n  render() {\n    return (\n      <div> Hello World </div>\n    )\n  }\n\n}\n\nexport default HelloWorld;\n
\n

The code above is just declaring the component, you still have to use it.

\n

Importing the component in your application gives you the ability to use a new tag in your render.

\n

This tag will be replaced with whatever you returned in your component render.

\n
import Nullstack from 'nullstack';\n\nimport './Application.scss';\n\nimport HelloWorld from './HelloWorld';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render({page}) {\n    return (\n      <main>\n        <h1> {page.title} </h1>\n        <a href=\"https://nullstack.app/documentation\" target=\"_blank\"> Read the documentation </a>\n        <HelloWorld />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Using HTML attributes

Nullstack JSX deviates a little from the spec.

\n

You can use the normal HTML attributes like class and for directly.

\n
<label for=\"input\" class=\"dont-label-me\"> I am a label </label>\n
\n

Headless components

If you want to skip rendering the component at all you can simply return false from the render.

\n
import Nullstack from 'nullstack';\n\nclass Headless extends Nullstack {\n \n  render() {\n    return false;\n  }\n\n}\n\nexport default Headless;\n
\n

This will allocate DOM space for when you decide to render markup there.

\n

This is also useful for conditional rendering.

\n

If all you want to do is to generate an invisible component you can skip defining the render method at all.

\n

Inner components

Instead of creating a new component just to organize code-splitting, you can create an inner component.

\n

Inner components are any method that the name starts with render followed by an uppercase character.

\n

Inner components share the same instance and scope as the main component, therefore, are very convenient to avoid problems like props drilling.

\n

To invoke the inner component use a JSX tag with the method name without the render prefix.

\n
import Nullstack from 'nullstack';\n\nclass Post extends Nullstack {\n\n  renderArticle() {\n    return (\n      <article> Content </article>\n    )\n  }\n\n  renderAside() {\n    return (\n      <aside> Related content </aside>\n    )\n  }\n \n  render() {\n    return (\n      <div>\n        <Article />\n        <Aside />\n      </div>\n    )\n  }\n\n}\n\nexport default HelloWorld;\n
\n
\n

💡 Nullstack will inject a constant reference to the function at transpile time in order to completely skip the runtime lookup process!

\n
\n

Boolean attributes

Attributes can be assigned as a boolean.

\n

When the value is false the attribute will not be rendered at all.

\n

When the value is true it will be rendered as a boolean attribute without a string value.

\n
<button disabled={false}> Button </button>\n
\n

You can shortcut attributes when you know the value will always be true.

\n
<button disabled> Button </button>\n
\n
\n

✨ Learn more about attributes.

\n
\n

Element tag

If you need to decide the tag name at runtime, you can use the element tag and set the tag attribute conditionally.

\n
<element tag={!!link ? 'a' : 'span'} href={link || false}>\n  some arbitrary text\n</element>\n
\n

When the tag attribute is omitted, Nullstack will default to a div.

\n

SVG Elements

SVG can be used as if it were any regular HTML tag.

\n

You can manipulate the SVG using attributes and events normally.

\n
<svg height={this.size} viewBox=\"0 0 100 100\">\n  <circle cx=\"50\" cy=\"50\" r=\"40\" onclick={this.grow} />\n</svg> \n
\n
\n

✨ Learn more about events.

\n
\n

Components with children

Your component can be invoked passing a block of content.

\n
<Header> \n  <h1> Hello World </h1>\n</Header>\n
\n

This doesn't automatically render the block since it wouldn't know where to place it.

\n

You can destructure the children on the render method and place it in your markup.

\n
import Nullstack from 'nullstack';\n\nclass Header extends Nullstack {\n \n  render({children}) {\n    return (\n      <div>{children}</div>\n    )\n  }\n\n}\n\nexport default Header;\n
\n
\n

✨ This is possible because the children key is part of the instance context.

\n
\n

Lists

You can map over lists without declaring a key.

\n

Lists that may change length must be wrapped in a parent element just for them.

\n
<ul>\n  {list.map((item) => <li>{item.name}</li>)}\n</ul>\n
\n

You can emulate a fixed-size list by returning false instead of an element to reserve dom space.

\n
{list.map((item) => (\n  item.visible ? <div>{item.name}</div> : false\n)}\n
\n

It's a nice practice to use inner components combined with lists to clean up your code.

\n
import Nullstack from 'nullstack';\n\nclass List extends Nullstack {\n\n  items = [\n    {visible: true, number: 1},\n    {visible: false, number: 2},\n    {visible: true, number: 3}\n  ]\n\n  renderItem({visible, number}) {\n    if(!visible) return false;\n    return (\n      <li> {number} </li>\n    )\n  }\n \n  render() {\n    return (\n      <ul>\n        {this.items.map((item) => <Item {...item} />)}\n      </ul>\n    )\n  }\n\n}\n\nexport default List;\n
\n
\n

✨ Sometimes you will notice keys in the map. Learn more about the instance key.

\n
\n

Inner HTML

You can set the inner HTML of an element with the html attribute.

\n

Links inside the HTML string will be replaced with routable anchors.

\n
import Nullstack from 'nullstack';\n\nclass Post extends Nullstack {\n\n  content = `\n    <h1> This is a Post </h1>\n    <a href=\"/other-post\">\n      Check this other post\n    </a>\n  `;\n \n  render() {\n    return (\n      <article html={this.content} />\n    )\n  }\n\n}\n\nexport default Post;\n
\n
\n

🔥 Be careful! When using user-generated HTML you are in risk of script injection

\n
\n

The head tag

Renderable components can render inside the head tag an unlimited number of times at any depth of the application.

\n

The head tag will only be updated during the server-side rendering process and changes will be ignored after the hydration process.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  // ...\n\n  render() {\n    return (\n      <main>\n        <div>\n          <head>\n            <link rel=\"preconnect\" href=\"https://www.googletagmanager.com\" />\n          </head>\n        </div>\n        <head>\n          <link rel=\"preload\" href=\"/roboto-v20-latin-300.woff2\" as=\"font\" type=\"font/woff2\" crossorigin />\n          <link rel=\"preload\" href=\"/crete-round-v9-latin-regular.woff2\" as=\"font\" type=\"font/woff2\" crossorigin />\n        </head>\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n
\n

🔥 You should not use the head tag to update metatags that Nullstack already controls

\n
\n

Next step

⚔ Add state to your component using stateful components.

\n","description":"Renderable components are very similar to web components they give you the ability to create new HTML tags that shortcut a group of other HTML tags"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Renderable Components - Nullstack","description":"Renderable components are very similar to web components they give you the ability to create new HTML tags that shortcut a group of other HTML tags"}} \ No newline at end of file diff --git a/docs/roboto-v20-latin-300.woff2 b/docs/roboto-v20-latin-300.woff2 deleted file mode 100644 index ef8c8836..00000000 Binary files a/docs/roboto-v20-latin-300.woff2 and /dev/null differ diff --git a/docs/roboto-v20-latin-500.woff2 b/docs/roboto-v20-latin-500.woff2 deleted file mode 100644 index 6362d7f6..00000000 Binary files a/docs/roboto-v20-latin-500.woff2 and /dev/null differ diff --git a/docs/robots.txt b/docs/robots.txt deleted file mode 100644 index 95a840fc..00000000 --- a/docs/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -User-Agent: * -Allow: / -Sitemap: https://nullstack.app/sitemap.xml \ No newline at end of file diff --git a/docs/routes-and-params.html b/docs/routes-and-params.html deleted file mode 100644 index a906c457..00000000 --- a/docs/routes-and-params.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Routes and Params - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Routes and Params

Nullstack has built-in routes, it would make no sense otherwise since web applications are expected to have hyperlinks.

-

Any tag can receive a route attribute, be it a component, inner component, or simple HTML tag.

-
import Nullstack from 'nullstack';
-import Page from './Page';
-
-class Application extends Nullstack {
-
-  renderHome() {
-    return (
-      <section> Home </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page" />
-        <abbr route="/abbreviations"> Abbreviations </abbr>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Links on Nullstack are simple a tags with the href value starting with "/".

-
<a href="/page/about"> About Page </a>
-
-
-

💡 On the client side the click event will push history without reloading the page.

-
-
-

✨ You can still assign your own click event to the tag without losing the framework behavior.

-
-

Params

The params key is an object proxy injected into every client instance.

-

Each query string param is mapped to this object.

-

By default any key you request from this object will return a string.

-

If the value is undefined it will return an empty string.

-

If the value is true or false it will return a boolean instead.

-
-

🐱‍💻 Bellow an exemple that visits "/books?expanded=true&page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    if(params.expanded) {
-      const page = parseInt(params.page) || 1;
-      this.books = await this.getBooks({page});
-    }
-  }
-
-}
-
-export default Books;
-
-

Assigning to a params key will cause a redirect to the route with updated params.

-

When you assign to a param, the value will be converted to JSON before being set.

-
-

💡 Redirects work in batches, so there is no performance loss in multiple assignments.

-
-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  handleClick({params}) {
-    params.filter = '';
-    params.page = 1;
-  }
-
-}
-
-export default Paginator;
-
-

Assigning an empty string to a param will remove it from the url.

-

Dynamic Segments

Part of the route can be an expression started with ":" followed by a param name.

-

This value will be matched against any string in the same directory position.

-

The value of the string in the URL will be assigned to the context params and functions below this point in the hierarchy will have access to the new key.

-
-

🐱‍💻 Bellow an example that visits "/category/suspense?page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    const page = parseInt(params.page) || 1;
-    const category = params.slug;
-    this.books = await this.getBooks({category, page});
-  }
-
-}
-
-export default Books;
-
-
import Nullstack from 'nullstack';
-import Books from './Books';
-
-class Application extends Nullstack {
-
-  render() {
-    <main>
-      <Books route="/category/:slug">
-    </main>
-  }
-
-}
-
-export default Application;
-
-

When a dynamic segment is changed, as for example moving from "/category/suspense" to "/category/comedy", the component will be terminated and a new instance will be created.

-

Changing a query param will not re-instantiate the component.

-

Children of the component will not be re-instantiated automatically, you can set the same route to the children or do it manually if you desire this behavior.

-
-

💡 The behavior mentioned above solves many of the problems you have to normally deal with manually.

-
-

Wildcards

Wildcards are routes declared with "*" as the attribute value.

-

These routes will match anything if nothing above it matches the requested URL.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <div route="*"> Wildcard </div>
-      </main>
-    )
-  }
-
-}
-
-

Wildcards can be prefixed with a segment.

-
-

✨ this is especially useful for engines that can be mounted in your application.

-
-
import Nullstack from 'nullstack';
-import Home from './Home';
-import BlogEngine from './BlogEngine';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <BlogEngine route="/blog/*" />
-      </main>
-    )
-  }
-
-}
-
-

Router

The router key is an object proxy injected into every client instance.

-

The router has two keys:

-
    -
  • url
  • -
  • path
  • -
-

The url key returns everything after the domain including the path and the query params as a string.

-

The path key returns only the path without query params.

-
-

💡 Both keys above automatically remove the trailing slash for convenience.

-
-

Assigning to url or path will cause a redirect.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  prepare({router}) {
-    if(router.path == '/') {
-      router.path = '/dashboard';
-    }
-  }
-
-}
-
-
-

💡 Under the hood a tags with params use the router.

-
-

Custom Events

Updating router.url or router.path will raise a custom event.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({router}) {
-    window.addEventListener(router.event, () => {
-      console.log(router.url);
-    });
-  }
-
-}
-
-export default Analytics;
-
-

Special anchors

Anchor tags accept some convenient special attributes besides the regular href.

-

You can set the params attribute with an object as the value.

-

The path will remain the same as the current router path, but the params will be replaced by the new params you specify.

-
<a params={{page: 1}}> First Page </a>
-
-

If you wish to just update some params and keep the others, you can use the javascript spread operator for that.

-
<a params={{...params, page: 1}}> First Page </a>
-
-

You can set the path attribute with a string starting with "/" and no query params.

-

The params will remain the same, but the path will be updated.

-
<a path="/category/suspense"> Suspense Books </a>
-
-

Both attributes above can be used at the same time.

-
<a path="/category/suspense" params={{...params, page: 1}}> Suspense Books </a>
-
-

Nested routes

The first route to be matched will be rendered.

-

The other elements with a route will not be rendered, however, elements on the same level without a route attribute will render normally.

-

The router will lookup for one route per dom depth level, this allows you to have nested routing behavior.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  renderPage() {
-    return (
-      <section>
-        <div route="/page/about"> About Page </div>
-        <div route="/page/contact"> Contact Page </div>
-      </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page/:slug" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn about two-way bindings.

-
- - - \ No newline at end of file diff --git a/docs/routes-and-params/index.html b/docs/routes-and-params/index.html deleted file mode 100644 index a906c457..00000000 --- a/docs/routes-and-params/index.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Routes and Params - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Routes and Params

Nullstack has built-in routes, it would make no sense otherwise since web applications are expected to have hyperlinks.

-

Any tag can receive a route attribute, be it a component, inner component, or simple HTML tag.

-
import Nullstack from 'nullstack';
-import Page from './Page';
-
-class Application extends Nullstack {
-
-  renderHome() {
-    return (
-      <section> Home </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page" />
-        <abbr route="/abbreviations"> Abbreviations </abbr>
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Links on Nullstack are simple a tags with the href value starting with "/".

-
<a href="/page/about"> About Page </a>
-
-
-

💡 On the client side the click event will push history without reloading the page.

-
-
-

✨ You can still assign your own click event to the tag without losing the framework behavior.

-
-

Params

The params key is an object proxy injected into every client instance.

-

Each query string param is mapped to this object.

-

By default any key you request from this object will return a string.

-

If the value is undefined it will return an empty string.

-

If the value is true or false it will return a boolean instead.

-
-

🐱‍💻 Bellow an exemple that visits "/books?expanded=true&page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    if(params.expanded) {
-      const page = parseInt(params.page) || 1;
-      this.books = await this.getBooks({page});
-    }
-  }
-
-}
-
-export default Books;
-
-

Assigning to a params key will cause a redirect to the route with updated params.

-

When you assign to a param, the value will be converted to JSON before being set.

-
-

💡 Redirects work in batches, so there is no performance loss in multiple assignments.

-
-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  handleClick({params}) {
-    params.filter = '';
-    params.page = 1;
-  }
-
-}
-
-export default Paginator;
-
-

Assigning an empty string to a param will remove it from the url.

-

Dynamic Segments

Part of the route can be an expression started with ":" followed by a param name.

-

This value will be matched against any string in the same directory position.

-

The value of the string in the URL will be assigned to the context params and functions below this point in the hierarchy will have access to the new key.

-
-

🐱‍💻 Bellow an example that visits "/category/suspense?page=2":

-
-
import Nullstack from 'nullstack';
-
-class Books extends Nullstack {
-
-  async initiate({params}) {
-    const page = parseInt(params.page) || 1;
-    const category = params.slug;
-    this.books = await this.getBooks({category, page});
-  }
-
-}
-
-export default Books;
-
-
import Nullstack from 'nullstack';
-import Books from './Books';
-
-class Application extends Nullstack {
-
-  render() {
-    <main>
-      <Books route="/category/:slug">
-    </main>
-  }
-
-}
-
-export default Application;
-
-

When a dynamic segment is changed, as for example moving from "/category/suspense" to "/category/comedy", the component will be terminated and a new instance will be created.

-

Changing a query param will not re-instantiate the component.

-

Children of the component will not be re-instantiated automatically, you can set the same route to the children or do it manually if you desire this behavior.

-
-

💡 The behavior mentioned above solves many of the problems you have to normally deal with manually.

-
-

Wildcards

Wildcards are routes declared with "*" as the attribute value.

-

These routes will match anything if nothing above it matches the requested URL.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <div route="*"> Wildcard </div>
-      </main>
-    )
-  }
-
-}
-
-

Wildcards can be prefixed with a segment.

-
-

✨ this is especially useful for engines that can be mounted in your application.

-
-
import Nullstack from 'nullstack';
-import Home from './Home';
-import BlogEngine from './BlogEngine';
-
-class Application extends Nullstack {
-
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <BlogEngine route="/blog/*" />
-      </main>
-    )
-  }
-
-}
-
-

Router

The router key is an object proxy injected into every client instance.

-

The router has two keys:

-
    -
  • url
  • -
  • path
  • -
-

The url key returns everything after the domain including the path and the query params as a string.

-

The path key returns only the path without query params.

-
-

💡 Both keys above automatically remove the trailing slash for convenience.

-
-

Assigning to url or path will cause a redirect.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  prepare({router}) {
-    if(router.path == '/') {
-      router.path = '/dashboard';
-    }
-  }
-
-}
-
-
-

💡 Under the hood a tags with params use the router.

-
-

Custom Events

Updating router.url or router.path will raise a custom event.

-
import Nullstack from 'nullstack';
-
-class Analytics extends Nullstack {
-
-  hydrate({router}) {
-    window.addEventListener(router.event, () => {
-      console.log(router.url);
-    });
-  }
-
-}
-
-export default Analytics;
-
-

Special anchors

Anchor tags accept some convenient special attributes besides the regular href.

-

You can set the params attribute with an object as the value.

-

The path will remain the same as the current router path, but the params will be replaced by the new params you specify.

-
<a params={{page: 1}}> First Page </a>
-
-

If you wish to just update some params and keep the others, you can use the javascript spread operator for that.

-
<a params={{...params, page: 1}}> First Page </a>
-
-

You can set the path attribute with a string starting with "/" and no query params.

-

The params will remain the same, but the path will be updated.

-
<a path="/category/suspense"> Suspense Books </a>
-
-

Both attributes above can be used at the same time.

-
<a path="/category/suspense" params={{...params, page: 1}}> Suspense Books </a>
-
-

Nested routes

The first route to be matched will be rendered.

-

The other elements with a route will not be rendered, however, elements on the same level without a route attribute will render normally.

-

The router will lookup for one route per dom depth level, this allows you to have nested routing behavior.

-
import Nullstack from 'nullstack';
-import Home from './Home';
-
-class Application extends Nullstack {
-
-  renderPage() {
-    return (
-      <section>
-        <div route="/page/about"> About Page </div>
-        <div route="/page/contact"> Contact Page </div>
-      </section>
-    )
-  }
- 
-  render({count}) {
-    return (
-      <main>
-        <Home route="/" />
-        <Page route="/page/:slug" />
-      </main>
-    )
-  }
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn about two-way bindings.

-
- - - \ No newline at end of file diff --git a/docs/routes-and-params/index.json b/docs/routes-and-params/index.json deleted file mode 100644 index a8b4ccaa..00000000 --- a/docs/routes-and-params/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Routes and Params","html":"

Nullstack has built-in routes, it would make no sense otherwise since web applications are expected to have hyperlinks.

\n

Any tag can receive a route attribute, be it a component, inner component, or simple HTML tag.

\n
import Nullstack from 'nullstack';\nimport Page from './Page';\n\nclass Application extends Nullstack {\n\n  renderHome() {\n    return (\n      <section> Home </section>\n    )\n  }\n \n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <Page route=\"/page\" />\n        <abbr route=\"/abbreviations\"> Abbreviations </abbr>\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Links

Links on Nullstack are simple a tags with the href value starting with "/".

\n
<a href=\"/page/about\"> About Page </a>\n
\n
\n

💡 On the client side the click event will push history without reloading the page.

\n
\n
\n

✨ You can still assign your own click event to the tag without losing the framework behavior.

\n
\n

Params

The params key is an object proxy injected into every client instance.

\n

Each query string param is mapped to this object.

\n

By default any key you request from this object will return a string.

\n

If the value is undefined it will return an empty string.

\n

If the value is true or false it will return a boolean instead.

\n
\n

🐱‍💻 Bellow an exemple that visits "/books?expanded=true&page=2":

\n
\n
import Nullstack from 'nullstack';\n\nclass Books extends Nullstack {\n\n  async initiate({params}) {\n    if(params.expanded) {\n      const page = parseInt(params.page) || 1;\n      this.books = await this.getBooks({page});\n    }\n  }\n\n}\n\nexport default Books;\n
\n

Assigning to a params key will cause a redirect to the route with updated params.

\n

When you assign to a param, the value will be converted to JSON before being set.

\n
\n

💡 Redirects work in batches, so there is no performance loss in multiple assignments.

\n
\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n\n  handleClick({params}) {\n    params.filter = '';\n    params.page = 1;\n  }\n\n}\n\nexport default Paginator;\n
\n

Assigning an empty string to a param will remove it from the url.

\n

Dynamic Segments

Part of the route can be an expression started with ":" followed by a param name.

\n

This value will be matched against any string in the same directory position.

\n

The value of the string in the URL will be assigned to the context params and functions below this point in the hierarchy will have access to the new key.

\n
\n

🐱‍💻 Bellow an example that visits "/category/suspense?page=2":

\n
\n
import Nullstack from 'nullstack';\n\nclass Books extends Nullstack {\n\n  async initiate({params}) {\n    const page = parseInt(params.page) || 1;\n    const category = params.slug;\n    this.books = await this.getBooks({category, page});\n  }\n\n}\n\nexport default Books;\n
\n
import Nullstack from 'nullstack';\nimport Books from './Books';\n\nclass Application extends Nullstack {\n\n  render() {\n    <main>\n      <Books route=\"/category/:slug\">\n    </main>\n  }\n\n}\n\nexport default Application;\n
\n

When a dynamic segment is changed, as for example moving from "/category/suspense" to "/category/comedy", the component will be terminated and a new instance will be created.

\n

Changing a query param will not re-instantiate the component.

\n

Children of the component will not be re-instantiated automatically, you can set the same route to the children or do it manually if you desire this behavior.

\n
\n

💡 The behavior mentioned above solves many of the problems you have to normally deal with manually.

\n
\n

Wildcards

Wildcards are routes declared with "*" as the attribute value.

\n

These routes will match anything if nothing above it matches the requested URL.

\n
import Nullstack from 'nullstack';\nimport Home from './Home';\n\nclass Application extends Nullstack {\n\n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <div route=\"*\"> Wildcard </div>\n      </main>\n    )\n  }\n\n}\n
\n

Wildcards can be prefixed with a segment.

\n
\n

✨ this is especially useful for engines that can be mounted in your application.

\n
\n
import Nullstack from 'nullstack';\nimport Home from './Home';\nimport BlogEngine from './BlogEngine';\n\nclass Application extends Nullstack {\n\n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <BlogEngine route=\"/blog/*\" />\n      </main>\n    )\n  }\n\n}\n
\n

Router

The router key is an object proxy injected into every client instance.

\n

The router has two keys:

\n
    \n
  • url
  • \n
  • path
  • \n
\n

The url key returns everything after the domain including the path and the query params as a string.

\n

The path key returns only the path without query params.

\n
\n

💡 Both keys above automatically remove the trailing slash for convenience.

\n
\n

Assigning to url or path will cause a redirect.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  prepare({router}) {\n    if(router.path == '/') {\n      router.path = '/dashboard';\n    }\n  }\n\n}\n
\n
\n

💡 Under the hood a tags with params use the router.

\n
\n

Custom Events

Updating router.url or router.path will raise a custom event.

\n
import Nullstack from 'nullstack';\n\nclass Analytics extends Nullstack {\n\n  hydrate({router}) {\n    window.addEventListener(router.event, () => {\n      console.log(router.url);\n    });\n  }\n\n}\n\nexport default Analytics;\n
\n

Special anchors

Anchor tags accept some convenient special attributes besides the regular href.

\n

You can set the params attribute with an object as the value.

\n

The path will remain the same as the current router path, but the params will be replaced by the new params you specify.

\n
<a params={{page: 1}}> First Page </a>\n
\n

If you wish to just update some params and keep the others, you can use the javascript spread operator for that.

\n
<a params={{...params, page: 1}}> First Page </a>\n
\n

You can set the path attribute with a string starting with "/" and no query params.

\n

The params will remain the same, but the path will be updated.

\n
<a path=\"/category/suspense\"> Suspense Books </a>\n
\n

Both attributes above can be used at the same time.

\n
<a path=\"/category/suspense\" params={{...params, page: 1}}> Suspense Books </a>\n
\n

Nested routes

The first route to be matched will be rendered.

\n

The other elements with a route will not be rendered, however, elements on the same level without a route attribute will render normally.

\n

The router will lookup for one route per dom depth level, this allows you to have nested routing behavior.

\n
import Nullstack from 'nullstack';\nimport Home from './Home';\n\nclass Application extends Nullstack {\n\n  renderPage() {\n    return (\n      <section>\n        <div route=\"/page/about\"> About Page </div>\n        <div route=\"/page/contact\"> Contact Page </div>\n      </section>\n    )\n  }\n \n  render({count}) {\n    return (\n      <main>\n        <Home route=\"/\" />\n        <Page route=\"/page/:slug\" />\n      </main>\n    )\n  }\n\n}\n\nexport default Application;\n
\n

Next step

⚔ Learn about two-way bindings.

\n","description":"Nullstack has built-in routes, it would make no sense otherwise since web applications are expected to have hyperlinks."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Routes and Params - Nullstack","description":"Nullstack has built-in routes, it would make no sense otherwise since web applications are expected to have hyperlinks."}} \ No newline at end of file diff --git a/docs/server-functions.html b/docs/server-functions.html deleted file mode 100644 index 0e92987a..00000000 --- a/docs/server-functions.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - Server Functions - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server Functions

Server functions are specialized microservices that at transpile time are converted into API entry points.

-

To flag a function as a server function, you must declare it as static async.

-

Being a static function means it has no access to the instance scope.

-

However, instead of calling the static version from the class, you must invoke it as an instance function.

-

Server functions can be called anytime in your code and are not limited to prerender steps.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-  }
-
-  async handleClick() {
-    await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Learn more about the server context.

-
-

Client behavior

When you call a server function from the client, the arguments will be serialized as JSON.

-

The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.

-

The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-    return context.count;
-  }
-
-  async handleClick() {
-    this.count = await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server behavior

Server functions will be used as local functions, simply aliasing the instance call to the class and merging the arguments with the server context.

-

Date Convenience

Dates are serialized as UTC in JSON and deserialized back to Date objects.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  async initiate() {
-    const date = new Date();
-    const verified = this.verifyDay({date});
-  }
-
-  static async verifyDay({date}) {
-    return date.getDay() === new Date().getDay();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Fetch Convenience

fetch is available in both server and client functions for the sake of isomorphy.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    const url = 'https://api.github.com/repos/nullstack/nullstack/issues';
-    const response = await fetch(url);
-    this.issues = await response.json();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server only imports

Imported dependencies that are only used inside server functions will be excluded from the client bundle.

-

This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.

-
import Nullstack from 'nullstack';
-import {readFileSync} from 'fs';
-import {Remarkable} from 'remarkable';
-
-class Application extends Nullstack {
-
-  static async getTasks() {
-    const readme = readFileSync('README.md', 'utf-8');
-    return new Remarkable().render(readme);
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Security

Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.

-
-

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

-
-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async getCount({request, count}) {
-    if(!request.session.user) return 0;
-    return count;
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

💡 Server functions are not exposed to the client.

-
-
-

✨ Learn more about the NJS file extension.

-
-

Reserved words

Server function names cannot collide with instance method names from the current class or its parent classes.

-

The following words cannot be used in server functions:

-
    -
  • prepare
  • -
  • initiate
  • -
  • hydrate
  • -
  • update
  • -
  • terminate
  • -
-

Server functions named start will not generate an API endpoint and can only be called by other server functions.

-

Caveats

Automatically generated API endpoints are not meant to be used by 3rd-party apps.

-

The URL and implementation may change between versions of Nullstack.

-
-

✨ If you want to build an API, learn more about how to create an API with Nullstack.

-
-

Next step

⚔ Learn about the context.

-
- - - \ No newline at end of file diff --git a/docs/server-functions/index.html b/docs/server-functions/index.html deleted file mode 100644 index 0e92987a..00000000 --- a/docs/server-functions/index.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - Server Functions - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server Functions

Server functions are specialized microservices that at transpile time are converted into API entry points.

-

To flag a function as a server function, you must declare it as static async.

-

Being a static function means it has no access to the instance scope.

-

However, instead of calling the static version from the class, you must invoke it as an instance function.

-

Server functions can be called anytime in your code and are not limited to prerender steps.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-  }
-
-  async handleClick() {
-    await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

✨ Learn more about the server context.

-
-

Client behavior

When you call a server function from the client, the arguments will be serialized as JSON.

-

The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.

-

The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async increment(context) {
-    context.count++;
-    return context.count;
-  }
-
-  async handleClick() {
-    this.count = await this.increment();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server behavior

Server functions will be used as local functions, simply aliasing the instance call to the class and merging the arguments with the server context.

-

Date Convenience

Dates are serialized as UTC in JSON and deserialized back to Date objects.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  async initiate() {
-    const date = new Date();
-    const verified = this.verifyDay({date});
-  }
-
-  static async verifyDay({date}) {
-    return date.getDay() === new Date().getDay();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Fetch Convenience

fetch is available in both server and client functions for the sake of isomorphy.

-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  // ...
-
-  async initiate() {
-    const url = 'https://api.github.com/repos/nullstack/nullstack/issues';
-    const response = await fetch(url);
-    this.issues = await response.json();
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-

Server only imports

Imported dependencies that are only used inside server functions will be excluded from the client bundle.

-

This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.

-
import Nullstack from 'nullstack';
-import {readFileSync} from 'fs';
-import {Remarkable} from 'remarkable';
-
-class Application extends Nullstack {
-
-  static async getTasks() {
-    const readme = readFileSync('README.md', 'utf-8');
-    return new Remarkable().render(readme);
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Security

Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.

-
-

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

-
-
import Nullstack from 'nullstack';
-
-class Component extends Nullstack {
-
-  static async getCount({request, count}) {
-    if(!request.session.user) return 0;
-    return count;
-  }
-
-  // ...
-
-}
-
-export default Component;
-
-
-

💡 Server functions are not exposed to the client.

-
-
-

✨ Learn more about the NJS file extension.

-
-

Reserved words

Server function names cannot collide with instance method names from the current class or its parent classes.

-

The following words cannot be used in server functions:

-
    -
  • prepare
  • -
  • initiate
  • -
  • hydrate
  • -
  • update
  • -
  • terminate
  • -
-

Server functions named start will not generate an API endpoint and can only be called by other server functions.

-

Caveats

Automatically generated API endpoints are not meant to be used by 3rd-party apps.

-

The URL and implementation may change between versions of Nullstack.

-
-

✨ If you want to build an API, learn more about how to create an API with Nullstack.

-
-

Next step

⚔ Learn about the context.

-
- - - \ No newline at end of file diff --git a/docs/server-functions/index.json b/docs/server-functions/index.json deleted file mode 100644 index 3b36177e..00000000 --- a/docs/server-functions/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Server Functions","html":"

Server functions are specialized microservices that at transpile time are converted into API entry points.

\n

To flag a function as a server function, you must declare it as static async.

\n

Being a static function means it has no access to the instance scope.

\n

However, instead of calling the static version from the class, you must invoke it as an instance function.

\n

Server functions can be called anytime in your code and are not limited to prerender steps.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  static async increment(context) {\n    context.count++;\n  }\n\n  async handleClick() {\n    await this.increment();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

✨ Learn more about the server context.

\n
\n

Client behavior

When you call a server function from the client, the arguments will be serialized as JSON.

\n

The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.

\n

The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  static async increment(context) {\n    context.count++;\n    return context.count;\n  }\n\n  async handleClick() {\n    this.count = await this.increment();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Server behavior

Server functions will be used as local functions, simply aliasing the instance call to the class and merging the arguments with the server context.

\n

Date Convenience

Dates are serialized as UTC in JSON and deserialized back to Date objects.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  async initiate() {\n    const date = new Date();\n    const verified = this.verifyDay({date});\n  }\n\n  static async verifyDay({date}) {\n    return date.getDay() === new Date().getDay();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Fetch Convenience

fetch is available in both server and client functions for the sake of isomorphy.

\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  // ...\n\n  async initiate() {\n    const url = 'https://api.github.com/repos/nullstack/nullstack/issues';\n    const response = await fetch(url);\n    this.issues = await response.json();\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n

Server only imports

Imported dependencies that are only used inside server functions will be excluded from the client bundle.

\n

This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.

\n
import Nullstack from 'nullstack';\nimport {readFileSync} from 'fs';\nimport {Remarkable} from 'remarkable';\n\nclass Application extends Nullstack {\n\n  static async getTasks() {\n    const readme = readFileSync('README.md', 'utf-8');\n    return new Remarkable().render(readme);\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

Security

Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.

\n
\n

🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.

\n
\n
import Nullstack from 'nullstack';\n\nclass Component extends Nullstack {\n\n  static async getCount({request, count}) {\n    if(!request.session.user) return 0;\n    return count;\n  }\n\n  // ...\n\n}\n\nexport default Component;\n
\n
\n

💡 Server functions are not exposed to the client.

\n
\n
\n

✨ Learn more about the NJS file extension.

\n
\n

Reserved words

Server function names cannot collide with instance method names from the current class or its parent classes.

\n

The following words cannot be used in server functions:

\n
    \n
  • prepare
  • \n
  • initiate
  • \n
  • hydrate
  • \n
  • update
  • \n
  • terminate
  • \n
\n

Server functions named start will not generate an API endpoint and can only be called by other server functions.

\n

Caveats

Automatically generated API endpoints are not meant to be used by 3rd-party apps.

\n

The URL and implementation may change between versions of Nullstack.

\n
\n

✨ If you want to build an API, learn more about how to create an API with Nullstack.

\n
\n

Next step

⚔ Learn about the context.

\n","description":"Server functions are specialized microservices that at transpile time are converted into API entry points"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Server Functions - Nullstack","description":"Server functions are specialized microservices that at transpile time are converted into API entry points"}} \ No newline at end of file diff --git a/docs/server-request-and-response.html b/docs/server-request-and-response.html deleted file mode 100644 index 63b981ec..00000000 --- a/docs/server-request-and-response.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - Server request and response - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server request and response

The server key

The server key is a proxy around the Express instance that runs Nullstack under the hood.

-

The server object is present only in the server context.

-

The following functions are tunneled back to the Express server:

-
    -
  • get
  • -
  • post
  • -
  • put
  • -
  • patch
  • -
  • delete
  • -
  • options
  • -
  • head
  • -
  • use
  • -
-
-

✨ If you wanna know how to make an API with Nullstack, this is the way.

-
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.get('/api/books', (request, response) => {
-      response.json({books: []});
-    });
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Other available keys are:

-
    -
  • port: integer
  • -
  • maximumPayloadSize: string
  • -
  • cors: object
  • -
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.port = 3000;
-    server.maximumPayloadSize = '5mb';
-    server.cors = {
-      origin: 'http://localhost:6969',
-      optionsSuccessStatus: 200
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

The cors object will be passed as the argument to express cors plugin.

-

Request and Response

Every server function context is merged with the original request and response objects from Express.

-

If you raise a response manually it will override the framework's server-side rendering response.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async getBooks({request, response}) {
-    if(!request.session.user) {
-      response.status(401).json({unauthorized: true});
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn about styles.

-
- - - \ No newline at end of file diff --git a/docs/server-request-and-response/index.html b/docs/server-request-and-response/index.html deleted file mode 100644 index 63b981ec..00000000 --- a/docs/server-request-and-response/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - Server request and response - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server request and response

The server key

The server key is a proxy around the Express instance that runs Nullstack under the hood.

-

The server object is present only in the server context.

-

The following functions are tunneled back to the Express server:

-
    -
  • get
  • -
  • post
  • -
  • put
  • -
  • patch
  • -
  • delete
  • -
  • options
  • -
  • head
  • -
  • use
  • -
-
-

✨ If you wanna know how to make an API with Nullstack, this is the way.

-
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.get('/api/books', (request, response) => {
-      response.json({books: []});
-    });
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Other available keys are:

-
    -
  • port: integer
  • -
  • maximumPayloadSize: string
  • -
  • cors: object
  • -
-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async start({server}) {
-    server.port = 3000;
-    server.maximumPayloadSize = '5mb';
-    server.cors = {
-      origin: 'http://localhost:6969',
-      optionsSuccessStatus: 200
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

The cors object will be passed as the argument to express cors plugin.

-

Request and Response

Every server function context is merged with the original request and response objects from Express.

-

If you raise a response manually it will override the framework's server-side rendering response.

-
import Nullstack from 'nullstack';
-
-class Application extends Nullstack {
-
-  static async getBooks({request, response}) {
-    if(!request.session.user) {
-      response.status(401).json({unauthorized: true});
-    }
-  }
-
-  // ...
-
-}
-
-export default Application;
-
-

Next step

⚔ Learn about styles.

-
- - - \ No newline at end of file diff --git a/docs/server-request-and-response/index.json b/docs/server-request-and-response/index.json deleted file mode 100644 index 2e624749..00000000 --- a/docs/server-request-and-response/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Server request and response","html":"

The server key

The server key is a proxy around the Express instance that runs Nullstack under the hood.

\n

The server object is present only in the server context.

\n

The following functions are tunneled back to the Express server:

\n
    \n
  • get
  • \n
  • post
  • \n
  • put
  • \n
  • patch
  • \n
  • delete
  • \n
  • options
  • \n
  • head
  • \n
  • use
  • \n
\n
\n

✨ If you wanna know how to make an API with Nullstack, this is the way.

\n
\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({server}) {\n    server.get('/api/books', (request, response) => {\n      response.json({books: []});\n    });\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

Other available keys are:

\n
    \n
  • port: integer
  • \n
  • maximumPayloadSize: string
  • \n
  • cors: object
  • \n
\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async start({server}) {\n    server.port = 3000;\n    server.maximumPayloadSize = '5mb';\n    server.cors = {\n      origin: 'http://localhost:6969',\n      optionsSuccessStatus: 200\n    }\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

The cors object will be passed as the argument to express cors plugin.

\n

Request and Response

Every server function context is merged with the original request and response objects from Express.

\n

If you raise a response manually it will override the framework's server-side rendering response.

\n
import Nullstack from 'nullstack';\n\nclass Application extends Nullstack {\n\n  static async getBooks({request, response}) {\n    if(!request.session.user) {\n      response.status(401).json({unauthorized: true});\n    }\n  }\n\n  // ...\n\n}\n\nexport default Application;\n
\n

Next step

⚔ Learn about styles.

\n","description":"The server key is a proxy around the express instance that runs Nullstack under the hood"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Server request and response - Nullstack","description":"The server key is a proxy around the express instance that runs Nullstack under the hood"}} \ No newline at end of file diff --git a/docs/server-side-rendering.html b/docs/server-side-rendering.html deleted file mode 100644 index 6d6cfe5c..00000000 --- a/docs/server-side-rendering.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - Server-Side Rendering - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server-Side Rendering

Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from.

-

Server-side rendering is good for SEO since it gives as fast as possible crawlable markup for search engines.

-

Nullstack starts the application for the user by first serving HTML of only the requested page with no overhead.

-

Before serving the HTML, Nullstack will wait for prepare and initiate of all components of that route to be resolved.

-

While server-side rendering all server functions run locally without the need to fetch an API, making the process even faster.

-

After the document is already painted in the browser, Nullstack loads the javascript client bundle and starts the hydration process.

-

No further requests to the server are made to recover the application state during hydration.

-

The page head will generate the necessary meta tags for SEO based on the contents of the project and page context keys.

-

Next step

⚔ Learn about static site generation.

-
- - - \ No newline at end of file diff --git a/docs/server-side-rendering/index.html b/docs/server-side-rendering/index.html deleted file mode 100644 index 6d6cfe5c..00000000 --- a/docs/server-side-rendering/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - Server-Side Rendering - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Server-Side Rendering

Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from.

-

Server-side rendering is good for SEO since it gives as fast as possible crawlable markup for search engines.

-

Nullstack starts the application for the user by first serving HTML of only the requested page with no overhead.

-

Before serving the HTML, Nullstack will wait for prepare and initiate of all components of that route to be resolved.

-

While server-side rendering all server functions run locally without the need to fetch an API, making the process even faster.

-

After the document is already painted in the browser, Nullstack loads the javascript client bundle and starts the hydration process.

-

No further requests to the server are made to recover the application state during hydration.

-

The page head will generate the necessary meta tags for SEO based on the contents of the project and page context keys.

-

Next step

⚔ Learn about static site generation.

-
- - - \ No newline at end of file diff --git a/docs/server-side-rendering/index.json b/docs/server-side-rendering/index.json deleted file mode 100644 index 573350f3..00000000 --- a/docs/server-side-rendering/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Server-Side Rendering","html":"

Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from.

\n

Server-side rendering is good for SEO since it gives as fast as possible crawlable markup for search engines.

\n

Nullstack starts the application for the user by first serving HTML of only the requested page with no overhead.

\n

Before serving the HTML, Nullstack will wait for prepare and initiate of all components of that route to be resolved.

\n

While server-side rendering all server functions run locally without the need to fetch an API, making the process even faster.

\n

After the document is already painted in the browser, Nullstack loads the javascript client bundle and starts the hydration process.

\n

No further requests to the server are made to recover the application state during hydration.

\n

The page head will generate the necessary meta tags for SEO based on the contents of the project and page context keys.

\n

Next step

⚔ Learn about static site generation.

\n","description":"Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Server-Side Rendering - Nullstack","description":"Nullstack optimizes SEO and response times out of the box by generating HTML for the route that you enter the application from"}} \ No newline at end of file diff --git a/docs/service-worker-9cdb5778f42a90a83e1427c9316c97d3.js b/docs/service-worker-9cdb5778f42a90a83e1427c9316c97d3.js deleted file mode 100644 index f2d2e47f..00000000 --- a/docs/service-worker-9cdb5778f42a90a83e1427c9316c97d3.js +++ /dev/null @@ -1,234 +0,0 @@ -self.context = { - "environment": { - "client": false, - "server": true, - "development": false, - "production": true, - "static": true, - "key": "9cdb5778f42a90a83e1427c9316c97d3" - }, - "project": { - "type": "website", - "display": "standalone", - "orientation": "portrait", - "scope": "/", - "root": "/", - "favicon": "/favicon-96x96.png", - "icons": { - "72": "/icon-72x72.png", - "96": "/icon-96x96.png", - "128": "/icon-128x128.png", - "144": "/icon-144x144.png", - "152": "/icon-152x152.png", - "180": "/icon-180x180.png", - "192": "/icon-192x192.png", - "384": "/icon-384x384.png", - "512": "/icon-512x512.png" - }, - "disallow": [], - "sitemap": true, - "cdn": "", - "protocol": "https", - "name": "Nullstack", - "domain": "nullstack.app", - "color": "#d22365", - "backgroundColor": "#2d3748" - }, - "settings": {}, - "worker": { - "enabled": true, - "fetching": false, - "preload": [ - "/404", - "/about", - "/application-startup", - "/context-data", - "/context-environment", - "/context-page", - "/context-project", - "/context-secrets", - "/context-settings", - "/context", - "/full-stack-lifecycle", - "/getting-started", - "/how-to-deploy-a-nullstack-application", - "/how-to-use-facebook-pixel-with-nullstack", - "/how-to-use-google-analytics-with-nullstack", - "/how-to-use-mongodb-with-nullstack", - "/instance-self", - "/njs-file-extension", - "/renderable-components", - "/routes-and-params", - "/server-functions", - "/server-request-and-response", - "/server-side-rendering", - "/service-worker", - "/stateful-components", - "/static-site-generation", - "/styles", - "/two-way-bindings", - "/documentation", - "/components", - "/about", - "/contributors", - "/roboto-v20-latin-300.woff2", - "/roboto-v20-latin-500.woff2", - "/crete-round-v9-latin-regular.woff2", - "/nullachan.png" - ], - "headers": {}, - "queues": {} - } -}; - -async function load(event) { - const response = await event.preloadResponse; - if (response) return response; - return await fetch(event.request); -} - -function toAPI(url) { - let [path, query] = url.split('?'); - if(path.indexOf('.') === -1) { - path += '/index.json'; - } - return query ? `${path}?${query}` : path; -} - -async function extractData(response) { - const html = await response.clone().text(); - const instancesLookup = 'window.instances = '; - const instances = html.split("\n").find((line) => line.indexOf(instancesLookup) > -1).split(instancesLookup)[1].slice(0, -1); - const pageLookup = 'window.page = '; - const page = html.split("\n").find((line) => line.indexOf(pageLookup) > -1).split(pageLookup)[1].slice(0, -1); - const json = `{"instances": ${instances}, "page": ${page}}`; - return new Response(json, { - headers: {'Content-Type': 'application/json'} - }); -} - -async function injectData(templateResponse, cachedDataResponse) { - const data = await cachedDataResponse.json(); - const input = await templateResponse.text(); - const output = input.split(`\n`).map((line) => { - if(line.indexOf('') > -1) { - return line.replace(/(<title\b[^>]*>)[^<>]*(<\/title>)/i, `$1${data.page.title}$2`); - } else if(line.indexOf('window.instances = ') > -1) { - return `window.instances = ${JSON.stringify(data.instances)};` - } else if(line.indexOf('window.page = ') > -1) { - return `window.page = ${JSON.stringify(data.page)};` - } else if(line.indexOf('window.worker = ') > -1) { - return line.replace('"online":false', '"online":true').replace('"responsive":false', '"responsive":true'); - } - return line; - }).join("\n"); - return new Response(output, { - headers: {'Content-Type': 'text/html'} - }); -} - -async function cacheFirst(event) { - const cache = await caches.open(self.context.environment.key); - const cachedResponse = await cache.match(event.request); - if(cachedResponse) return cachedResponse; - const response = await load(event); - await cache.put(event.request, response.clone()); - return response; -} - -async function staleWhileRevalidate(event) { - const cache = await caches.open(self.context.environment.key); - const cachedResponse = await cache.match(event.request); - const networkResponsePromise = load(event); - event.waitUntil(async function() { - const networkResponse = await networkResponsePromise; - await cache.put(event.request, networkResponse.clone()); - }()); - return cachedResponse || networkResponsePromise; -} - -async function networkFirst(event) { - const cache = await caches.open(self.context.environment.key); - try { - const networkResponse = await load(event); - await cache.put(event.request, networkResponse.clone()); - return networkResponse; - } catch(error) { - return await cache.match(event.request); - } -} - -async function networkDataFirst(event) { - const cache = await caches.open(self.context.environment.key); - const url = new URL(event.request.url); - const api = url.pathname + '/index.json'; - try { - const response = await load(event); - const dataResponse = await extractData(response); - await cache.put(api, dataResponse); - return response; - } catch(error) { - const fallbackResponse = await cache.match(`/offline-${self.context.environment.key}/index.html`); - const cachedDataResponse = await cache.match(api); - if(cachedDataResponse) { - return await injectData(fallbackResponse, cachedDataResponse); - } else { - return fallbackResponse; - } - } -} - -function install(event) { - const urls = [ - '/', - ...self.context.worker.preload.map(toAPI), - '/offline-' + self.context.environment.key + '/index.html', - '/client-' + self.context.environment.key + '.css', - '/client-' + self.context.environment.key + '.js', - '/manifest-' + self.context.environment.key + '.json' - ]; - event.waitUntil(async function() { - const cache = await caches.open(self.context.environment.key); - await cache.addAll([...new Set(urls)]); - const homeResponse = await cache.match('/'); - const homeDataResponse = await extractData(homeResponse); - await cache.put('/index.json', homeDataResponse); - self.skipWaiting(); - }()); -} - -self.addEventListener('install', install); - -function activate(event) { - event.waitUntil(async function() { - const cacheNames = await caches.keys(); - const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key); - await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName))); - if (self.registration.navigationPreload) { - await self.registration.navigationPreload.enable(); - } - self.clients.claim(); - }()); -} - -self.addEventListener('activate', activate); - -function staticStrategy(event) { - event.waitUntil(async function() { - const url = new URL(event.request.url); - if(url.origin !== location.origin) return; - if(event.request.method !== 'GET') return; - if(url.pathname.indexOf(self.context.environment.key) > -1) { - return event.respondWith(cacheFirst(event)); - } - if(url.pathname.indexOf('.') > -1) { - return event.respondWith(staleWhileRevalidate(event)); - } - if(url.pathname === '/') { - return event.respondWith(networkFirst(event)); - } - event.respondWith(networkDataFirst(event)); - }()); -} - -self.addEventListener('fetch', staticStrategy); \ No newline at end of file diff --git a/docs/service-worker.html b/docs/service-worker.html deleted file mode 100644 index 222b4be2..00000000 --- a/docs/service-worker.html +++ /dev/null @@ -1,292 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <meta name="generator" content="Created with Nullstack - https://nullstack.app" /> - <title>Context Service Worker - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Service Worker

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in server context
  • -
  • readonly in client context
  • -
-

It gives you granular control of your PWA behavior.

-

worker keys will be used to generate the service worker file and should be set during the application startup.

-

worker keys are frozen after the application startup.

-

The following keys are available in the object during the startup:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • headers: object
  • -
-

The enabled key defines if the service worker will be automatically registered by Nullstack.

-

By default enabled is set to true on production mode and false on development mode.

-

preload is an array of paths that will be cached when the service worker is installed.

-

The assets required to start the application will be preloaded automatically, and you should configure only the extra pages you want to have available offline.

-
import Nullstack from 'nullstack';
-import path from 'path';
-import {readdirSync} from 'fs';
-
-class Application extends Nullstack {
-
-  static async start({worker}) {
-    const articles = readdirSync(path.join(__dirname, '..', 'articles'));
-    worker.preload = [
-      ...articles.map((article) => '/' + article.replace('.md', '')),
-      '/nullstack.svg',
-      '/documentation',
-      '/components'
-    ]
-  }
-  
-  // ...
-
-}
-
-export default Application;
-
-
-

💡 the example above is extracted from this repository and allows the documentation to be fully accessible offline.

-
-

The following keys are available as readonly in the client context:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • online: boolean
  • -
  • fetching: boolean
  • -
  • responsive: boolean
  • -
  • installation: BeforeInstallPromptEvent
  • -
  • registration: ServiceWorkerRegistration
  • -
  • loading: object
  • -
-

The following keys are available as readwrite in the client context:

-
    -
  • headers: object
  • -
-

The responsive key determines if the application has all the responses it needs to render the current page.

-

Nullstack will try to keep your application responsive as long as possible and set the key to false only when there are no ways of retrieving any response from the network or offline according to the fetch strategy for the environment.

-

The online key will listen for network events and rerender the application when navigator.onLine value changes.

-

When the application is back online Nullstack will try to make the application responsive again and rerender if necessary.

-
import Nullstack from 'nullstack';
-// ...
-
-class Application extends Nullstack {
- 
-  // ...
-
-  render({worker}) {
-    if(!worker.responsive) {
-      return <OfflineWarning />
-    }
-    return (
-      <main>
-        <Home route="/" />
-      </main>
-    )
-  }
-
-}
-
-

You can access the current service worker registration and installation from the worker key to control the flow of your PWA.

-

The registration key refers to the service worker registration and will be only available once the registration process is complete.

-

The installation key refers to the deferred installation prompt event and will only be available if the beforeinstallprompt event is triggered.

-
import Nullstack from 'nullstack';
-
-class PWAInstaller extends Nullstack {
-
-  installed = false;
-  hidden = false;
-
-  async prompt({worker}) {
-    try {
-      worker.installation.prompt();
-      const {outcome} = await worker.installation.userChoice;
-      if (outcome === 'accepted') {
-        console.log('User accepted the A2HS prompt');
-      } else {
-        console.log('User dismissed the A2HS prompt');
-      }
-    } finally {
-      this.hidden = true;
-    }
-  }
-  
-  render({worker, project}) {
-    if(this.hidden) return false;
-    if(!worker.installation) return false;
-    return (
-      <div>
-        <img src={project.favicon} />
-        <p> Do you want to add {project.name} to your home screen?</p>
-        <button onclick={this.prompt}> Install </button>
-        <button onclick={{hidden: true}}> Not Now </button>
-      </div>
-    )
-  }
-
-}
-
-export default PWAInstaller;
-
-

Loading Screens

When a server function is called fetching will be set to true until the response is resolved.

-

When a server function is called a key with the name of the server function invoked will be set to true in the loading key until the response is resolved.

-

Any key you invoke on the loading object will always return a boolean instead of undefined for consistency.

-

When the server is emulating the client context for server-side rendering, every key of the loading object will always return false, saving multiple render cycles in performance.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  static async save() {
-    // ...
-  }
-
-  async submit() {
-    await this.save();
-  }
- 
-  render({worker}) {
-    return (
-      <form onsubmit={this.save}> 
-        {worker.fetching && 
-          <span> loading... </span>
-        }
-        <button disabled={worker.loading.save}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-

Custom headers

You can use the headers key to configure the headers that the worker will use when fetching a server function.

-
-

🔥 Headers will be ignored when a server function is called during the server-side rendering process.

-
-
import Nullstack from 'nullstack';
-
-class LoginPage extends Nullstack {
-
-  // ...
-
-  async submit({worker}) {
-    // ...
-    this.headers['Authorization'] = `Bearer ${token}`;
-    // ...
-  }
-
-  static async authorize({request}) {
-    const authorization = request.headers['Authorization'];
-    // ...
-  }
-  
-  // ...
-
-}
-
-
-export default LoginPage;
-
-
-

✨ Learn more about the server request and response

-
-

Server-side render strategy

    -
  • Requests for different origins will be fetched normally;
  • -
  • Requests that are not GET will be fetched normally;
  • -
  • Fingerprinted assets will be loaded into cache at installation time;
  • -
  • Fingerprinted assets will be loaded from cache first then fallback to the network if needed;
  • -
  • Paths with an extension will be retrieved stale and update the cache in the background for subsequent request;
  • -
  • Navigation paths will be loaded from the network then fallback to a page in which worker.responsive and worker.online are set to false;
  • -
-

Static-site generation strategy

    -
  • Requests for different origins will be fetched normally;
  • -
  • Requests that are not GET will be fetched normally;
  • -
  • Fingerprinted assets will be loaded into cache at installation time;
  • -
  • Fingerprinted assets will be loaded from cache first then fallback to the network if needed;
  • -
  • Paths with an extension will be retrieved stale and update the cache in the background for subsequent request;
  • -
  • The home page will be loaded network first and then fallback to a cached copy if needed;
  • -
  • Navigation paths will instead load only the static API data and merge it with the application template to generate a response.
  • -
  • Navigating to a static route will cache only the data of that page;
  • -
  • When data is not available in the cache or network it will fallback to a page in which worker.responsive and worker.online are set to false;
  • -
-

Custom Strategy

Nullstack will install automatically your service worker if enabled is set to true with the following events:

-
    -
  • install
  • -
  • activate
  • -
  • fetch
  • -
-

You can override any of those events by creating a service-worker.js in the public folder;

-

If any of the keywords above are found Nullstack will inject your function in the service worker code instead of the default.

-

For convenience a context key is injected in the service worker self with the following keys:

- -
function activate(event) {
-  event.waitUntil(async function() {
-    const cacheNames = await caches.keys();
-    const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key);
-    await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName)));
-    if (self.registration.navigationPreload) {
-      await self.registration.navigationPreload.enable();
-    }
-    self.clients.claim();
-  }());
-}
-
-self.addEventListener('activate', activate);
-
-
-

💡 The example above is extracted from the generated service worker and uses self.context.environment.key

-
-

Next step

⚔ Learn how to deploy a Nullstack application.

-
- - - \ No newline at end of file diff --git a/docs/service-worker/index.html b/docs/service-worker/index.html deleted file mode 100644 index 222b4be2..00000000 --- a/docs/service-worker/index.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - - Context Service Worker - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Context Service Worker

    -
  • Type: object
  • -
  • Origin: Nullstack Context
  • -
  • Availability: server/client
  • -
  • readwrite in server context
  • -
  • readonly in client context
  • -
-

It gives you granular control of your PWA behavior.

-

worker keys will be used to generate the service worker file and should be set during the application startup.

-

worker keys are frozen after the application startup.

-

The following keys are available in the object during the startup:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • headers: object
  • -
-

The enabled key defines if the service worker will be automatically registered by Nullstack.

-

By default enabled is set to true on production mode and false on development mode.

-

preload is an array of paths that will be cached when the service worker is installed.

-

The assets required to start the application will be preloaded automatically, and you should configure only the extra pages you want to have available offline.

-
import Nullstack from 'nullstack';
-import path from 'path';
-import {readdirSync} from 'fs';
-
-class Application extends Nullstack {
-
-  static async start({worker}) {
-    const articles = readdirSync(path.join(__dirname, '..', 'articles'));
-    worker.preload = [
-      ...articles.map((article) => '/' + article.replace('.md', '')),
-      '/nullstack.svg',
-      '/documentation',
-      '/components'
-    ]
-  }
-  
-  // ...
-
-}
-
-export default Application;
-
-
-

💡 the example above is extracted from this repository and allows the documentation to be fully accessible offline.

-
-

The following keys are available as readonly in the client context:

-
    -
  • enabled: boolean
  • -
  • preload: string array (relative paths)
  • -
  • online: boolean
  • -
  • fetching: boolean
  • -
  • responsive: boolean
  • -
  • installation: BeforeInstallPromptEvent
  • -
  • registration: ServiceWorkerRegistration
  • -
  • loading: object
  • -
-

The following keys are available as readwrite in the client context:

-
    -
  • headers: object
  • -
-

The responsive key determines if the application has all the responses it needs to render the current page.

-

Nullstack will try to keep your application responsive as long as possible and set the key to false only when there are no ways of retrieving any response from the network or offline according to the fetch strategy for the environment.

-

The online key will listen for network events and rerender the application when navigator.onLine value changes.

-

When the application is back online Nullstack will try to make the application responsive again and rerender if necessary.

-
import Nullstack from 'nullstack';
-// ...
-
-class Application extends Nullstack {
- 
-  // ...
-
-  render({worker}) {
-    if(!worker.responsive) {
-      return <OfflineWarning />
-    }
-    return (
-      <main>
-        <Home route="/" />
-      </main>
-    )
-  }
-
-}
-
-

You can access the current service worker registration and installation from the worker key to control the flow of your PWA.

-

The registration key refers to the service worker registration and will be only available once the registration process is complete.

-

The installation key refers to the deferred installation prompt event and will only be available if the beforeinstallprompt event is triggered.

-
import Nullstack from 'nullstack';
-
-class PWAInstaller extends Nullstack {
-
-  installed = false;
-  hidden = false;
-
-  async prompt({worker}) {
-    try {
-      worker.installation.prompt();
-      const {outcome} = await worker.installation.userChoice;
-      if (outcome === 'accepted') {
-        console.log('User accepted the A2HS prompt');
-      } else {
-        console.log('User dismissed the A2HS prompt');
-      }
-    } finally {
-      this.hidden = true;
-    }
-  }
-  
-  render({worker, project}) {
-    if(this.hidden) return false;
-    if(!worker.installation) return false;
-    return (
-      <div>
-        <img src={project.favicon} />
-        <p> Do you want to add {project.name} to your home screen?</p>
-        <button onclick={this.prompt}> Install </button>
-        <button onclick={{hidden: true}}> Not Now </button>
-      </div>
-    )
-  }
-
-}
-
-export default PWAInstaller;
-
-

Loading Screens

When a server function is called fetching will be set to true until the response is resolved.

-

When a server function is called a key with the name of the server function invoked will be set to true in the loading key until the response is resolved.

-

Any key you invoke on the loading object will always return a boolean instead of undefined for consistency.

-

When the server is emulating the client context for server-side rendering, every key of the loading object will always return false, saving multiple render cycles in performance.

-
import Nullstack from 'nullstack';
-
-class Page extends Nullstack {
-
-  static async save() {
-    // ...
-  }
-
-  async submit() {
-    await this.save();
-  }
- 
-  render({worker}) {
-    return (
-      <form onsubmit={this.save}> 
-        {worker.fetching && 
-          <span> loading... </span>
-        }
-        <button disabled={worker.loading.save}> 
-          Save
-        </button>
-      </form>
-    )
-  }
-
-}
-
-export default Page;
-
-

Custom headers

You can use the headers key to configure the headers that the worker will use when fetching a server function.

-
-

🔥 Headers will be ignored when a server function is called during the server-side rendering process.

-
-
import Nullstack from 'nullstack';
-
-class LoginPage extends Nullstack {
-
-  // ...
-
-  async submit({worker}) {
-    // ...
-    this.headers['Authorization'] = `Bearer ${token}`;
-    // ...
-  }
-
-  static async authorize({request}) {
-    const authorization = request.headers['Authorization'];
-    // ...
-  }
-  
-  // ...
-
-}
-
-
-export default LoginPage;
-
-
-

✨ Learn more about the server request and response

-
-

Server-side render strategy

    -
  • Requests for different origins will be fetched normally;
  • -
  • Requests that are not GET will be fetched normally;
  • -
  • Fingerprinted assets will be loaded into cache at installation time;
  • -
  • Fingerprinted assets will be loaded from cache first then fallback to the network if needed;
  • -
  • Paths with an extension will be retrieved stale and update the cache in the background for subsequent request;
  • -
  • Navigation paths will be loaded from the network then fallback to a page in which worker.responsive and worker.online are set to false;
  • -
-

Static-site generation strategy

    -
  • Requests for different origins will be fetched normally;
  • -
  • Requests that are not GET will be fetched normally;
  • -
  • Fingerprinted assets will be loaded into cache at installation time;
  • -
  • Fingerprinted assets will be loaded from cache first then fallback to the network if needed;
  • -
  • Paths with an extension will be retrieved stale and update the cache in the background for subsequent request;
  • -
  • The home page will be loaded network first and then fallback to a cached copy if needed;
  • -
  • Navigation paths will instead load only the static API data and merge it with the application template to generate a response.
  • -
  • Navigating to a static route will cache only the data of that page;
  • -
  • When data is not available in the cache or network it will fallback to a page in which worker.responsive and worker.online are set to false;
  • -
-

Custom Strategy

Nullstack will install automatically your service worker if enabled is set to true with the following events:

-
    -
  • install
  • -
  • activate
  • -
  • fetch
  • -
-

You can override any of those events by creating a service-worker.js in the public folder;

-

If any of the keywords above are found Nullstack will inject your function in the service worker code instead of the default.

-

For convenience a context key is injected in the service worker self with the following keys:

- -
function activate(event) {
-  event.waitUntil(async function() {
-    const cacheNames = await caches.keys();
-    const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key);
-    await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName)));
-    if (self.registration.navigationPreload) {
-      await self.registration.navigationPreload.enable();
-    }
-    self.clients.claim();
-  }());
-}
-
-self.addEventListener('activate', activate);
-
-
-

💡 The example above is extracted from the generated service worker and uses self.context.environment.key

-
-

Next step

⚔ Learn how to deploy a Nullstack application.

-
- - - \ No newline at end of file diff --git a/docs/service-worker/index.json b/docs/service-worker/index.json deleted file mode 100644 index d9c49d5d..00000000 --- a/docs/service-worker/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Context Service Worker","html":"
    \n
  • Type: object
  • \n
  • Origin: Nullstack Context
  • \n
  • Availability: server/client
  • \n
  • readwrite in server context
  • \n
  • readonly in client context
  • \n
\n

It gives you granular control of your PWA behavior.

\n

worker keys will be used to generate the service worker file and should be set during the application startup.

\n

worker keys are frozen after the application startup.

\n

The following keys are available in the object during the startup:

\n
    \n
  • enabled: boolean
  • \n
  • preload: string array (relative paths)
  • \n
  • headers: object
  • \n
\n

The enabled key defines if the service worker will be automatically registered by Nullstack.

\n

By default enabled is set to true on production mode and false on development mode.

\n

preload is an array of paths that will be cached when the service worker is installed.

\n

The assets required to start the application will be preloaded automatically, and you should configure only the extra pages you want to have available offline.

\n
import Nullstack from 'nullstack';\nimport path from 'path';\nimport {readdirSync} from 'fs';\n\nclass Application extends Nullstack {\n\n  static async start({worker}) {\n    const articles = readdirSync(path.join(__dirname, '..', 'articles'));\n    worker.preload = [\n      ...articles.map((article) => '/' + article.replace('.md', '')),\n      '/nullstack.svg',\n      '/documentation',\n      '/components'\n    ]\n  }\n  \n  // ...\n\n}\n\nexport default Application;\n
\n
\n

💡 the example above is extracted from this repository and allows the documentation to be fully accessible offline.

\n
\n

The following keys are available as readonly in the client context:

\n
    \n
  • enabled: boolean
  • \n
  • preload: string array (relative paths)
  • \n
  • online: boolean
  • \n
  • fetching: boolean
  • \n
  • responsive: boolean
  • \n
  • installation: BeforeInstallPromptEvent
  • \n
  • registration: ServiceWorkerRegistration
  • \n
  • loading: object
  • \n
\n

The following keys are available as readwrite in the client context:

\n
    \n
  • headers: object
  • \n
\n

The responsive key determines if the application has all the responses it needs to render the current page.

\n

Nullstack will try to keep your application responsive as long as possible and set the key to false only when there are no ways of retrieving any response from the network or offline according to the fetch strategy for the environment.

\n

The online key will listen for network events and rerender the application when navigator.onLine value changes.

\n

When the application is back online Nullstack will try to make the application responsive again and rerender if necessary.

\n
import Nullstack from 'nullstack';\n// ...\n\nclass Application extends Nullstack {\n \n  // ...\n\n  render({worker}) {\n    if(!worker.responsive) {\n      return <OfflineWarning />\n    }\n    return (\n      <main>\n        <Home route=\"/\" />\n      </main>\n    )\n  }\n\n}\n
\n

You can access the current service worker registration and installation from the worker key to control the flow of your PWA.

\n

The registration key refers to the service worker registration and will be only available once the registration process is complete.

\n

The installation key refers to the deferred installation prompt event and will only be available if the beforeinstallprompt event is triggered.

\n
import Nullstack from 'nullstack';\n\nclass PWAInstaller extends Nullstack {\n\n  installed = false;\n  hidden = false;\n\n  async prompt({worker}) {\n    try {\n      worker.installation.prompt();\n      const {outcome} = await worker.installation.userChoice;\n      if (outcome === 'accepted') {\n        console.log('User accepted the A2HS prompt');\n      } else {\n        console.log('User dismissed the A2HS prompt');\n      }\n    } finally {\n      this.hidden = true;\n    }\n  }\n  \n  render({worker, project}) {\n    if(this.hidden) return false;\n    if(!worker.installation) return false;\n    return (\n      <div>\n        <img src={project.favicon} />\n        <p> Do you want to add {project.name} to your home screen?</p>\n        <button onclick={this.prompt}> Install </button>\n        <button onclick={{hidden: true}}> Not Now </button>\n      </div>\n    )\n  }\n\n}\n\nexport default PWAInstaller;\n
\n

Loading Screens

When a server function is called fetching will be set to true until the response is resolved.

\n

When a server function is called a key with the name of the server function invoked will be set to true in the loading key until the response is resolved.

\n

Any key you invoke on the loading object will always return a boolean instead of undefined for consistency.

\n

When the server is emulating the client context for server-side rendering, every key of the loading object will always return false, saving multiple render cycles in performance.

\n
import Nullstack from 'nullstack';\n\nclass Page extends Nullstack {\n\n  static async save() {\n    // ...\n  }\n\n  async submit() {\n    await this.save();\n  }\n \n  render({worker}) {\n    return (\n      <form onsubmit={this.save}> \n        {worker.fetching && \n          <span> loading... </span>\n        }\n        <button disabled={worker.loading.save}> \n          Save\n        </button>\n      </form>\n    )\n  }\n\n}\n\nexport default Page;\n
\n

Custom headers

You can use the headers key to configure the headers that the worker will use when fetching a server function.

\n
\n

🔥 Headers will be ignored when a server function is called during the server-side rendering process.

\n
\n
import Nullstack from 'nullstack';\n\nclass LoginPage extends Nullstack {\n\n  // ...\n\n  async submit({worker}) {\n    // ...\n    this.headers['Authorization'] = `Bearer ${token}`;\n    // ...\n  }\n\n  static async authorize({request}) {\n    const authorization = request.headers['Authorization'];\n    // ...\n  }\n  \n  // ...\n\n}\n\n\nexport default LoginPage;\n
\n
\n

✨ Learn more about the server request and response

\n
\n

Server-side render strategy

    \n
  • Requests for different origins will be fetched normally;
  • \n
  • Requests that are not GET will be fetched normally;
  • \n
  • Fingerprinted assets will be loaded into cache at installation time;
  • \n
  • Fingerprinted assets will be loaded from cache first then fallback to the network if needed;
  • \n
  • Paths with an extension will be retrieved stale and update the cache in the background for subsequent request;
  • \n
  • Navigation paths will be loaded from the network then fallback to a page in which worker.responsive and worker.online are set to false;
  • \n
\n

Static-site generation strategy

    \n
  • Requests for different origins will be fetched normally;
  • \n
  • Requests that are not GET will be fetched normally;
  • \n
  • Fingerprinted assets will be loaded into cache at installation time;
  • \n
  • Fingerprinted assets will be loaded from cache first then fallback to the network if needed;
  • \n
  • Paths with an extension will be retrieved stale and update the cache in the background for subsequent request;
  • \n
  • The home page will be loaded network first and then fallback to a cached copy if needed;
  • \n
  • Navigation paths will instead load only the static API data and merge it with the application template to generate a response.
  • \n
  • Navigating to a static route will cache only the data of that page;
  • \n
  • When data is not available in the cache or network it will fallback to a page in which worker.responsive and worker.online are set to false;
  • \n
\n

Custom Strategy

Nullstack will install automatically your service worker if enabled is set to true with the following events:

\n
    \n
  • install
  • \n
  • activate
  • \n
  • fetch
  • \n
\n

You can override any of those events by creating a service-worker.js in the public folder;

\n

If any of the keywords above are found Nullstack will inject your function in the service worker code instead of the default.

\n

For convenience a context key is injected in the service worker self with the following keys:

\n\n
function activate(event) {\n  event.waitUntil(async function() {\n    const cacheNames = await caches.keys();\n    const cachesToDelete = cacheNames.filter(cacheName => cacheName !== self.context.environment.key);\n    await Promise.all(cachesToDelete.map((cacheName) => caches.delete(cacheName)));\n    if (self.registration.navigationPreload) {\n      await self.registration.navigationPreload.enable();\n    }\n    self.clients.claim();\n  }());\n}\n\nself.addEventListener('activate', activate);\n
\n
\n

💡 The example above is extracted from the generated service worker and uses self.context.environment.key

\n
\n

Next step

⚔ Learn how to deploy a Nullstack application.

\n","description":"The worker object is a proxy in the Nullstack Context available in both client and server and gives you granular control of your PWA behavior"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Context Service Worker - Nullstack","description":"The worker object is a proxy in the Nullstack Context available in both client and server and gives you granular control of your PWA behavior"}} \ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml deleted file mode 100644 index 889e3d3f..00000000 --- a/docs/sitemap.xml +++ /dev/null @@ -1 +0,0 @@ -https://nullstack.app/2021-03-301.0https://nullstack.app/documentation2021-03-300.8https://nullstack.app/components2021-03-300.3https://nullstack.app/contributors2021-03-30https://nullstack.app/pt-br2021-03-301.0https://nullstack.app/getting-started2021-03-30https://nullstack.app/server-side-rendering2021-03-30https://nullstack.app/full-stack-lifecycle2021-03-30https://nullstack.app/static-site-generation2021-03-30https://nullstack.app/stateful-components2021-03-30https://nullstack.app/two-way-bindings2021-03-30https://nullstack.app/routes-and-params2021-03-30https://nullstack.app/about2021-03-30https://nullstack.app/waifu2021-03-30https://nullstack.app/renderable-components2021-03-30https://nullstack.app/server-functions2021-03-30https://nullstack.app/context2021-03-30https://nullstack.app/application-startup2021-03-30https://nullstack.app/context-data2021-03-30https://nullstack.app/context-environment2021-03-30https://nullstack.app/context-page2021-03-30https://nullstack.app/context-project2021-03-30https://nullstack.app/context-settings2021-03-30https://nullstack.app/context-secrets2021-03-30https://nullstack.app/instance-self2021-03-30https://nullstack.app/server-request-and-response2021-03-30https://nullstack.app/styles2021-03-30https://nullstack.app/njs-file-extension2021-03-30https://nullstack.app/service-worker2021-03-30https://nullstack.app/how-to-deploy-a-nullstack-application2021-03-30https://nullstack.app/how-to-use-mongodb-with-nullstack2021-03-30https://nullstack.app/how-to-use-google-analytics-with-nullstack2021-03-30https://nullstack.app/how-to-use-facebook-pixel-with-nullstack2021-03-30https://nullstack.app/pt-br/documentacao2021-03-300.8https://nullstack.app/pt-br/componentes2021-03-300.3https://nullstack.app/pt-br/contribuidores2021-03-30https://nullstack.app/pt-br/comecando2021-03-30https://nullstack.app/pt-br/renderizando-no-servidor2021-03-30https://nullstack.app/pt-br/ciclo-de-vida-full-stack2021-03-30https://nullstack.app/pt-br/geracao-de-sites-estaticos2021-03-30https://nullstack.app/pt-br/componentes-com-estado2021-03-30https://nullstack.app/pt-br/vinculo-bidirecional2021-03-30https://nullstack.app/pt-br/rotas-e-parametros2021-03-30https://nullstack.app/pt-br/sobre2021-03-30https://nullstack.app/pt-br/waifu2021-03-30https://nullstack.app/pt-br/componentes-renderizaveis2021-03-30https://nullstack.app/pt-br/funcoes-de-servidor2021-03-30https://nullstack.app/pt-br/contexto2021-03-30https://nullstack.app/pt-br/inicializacao-da-aplicacao2021-03-30https://nullstack.app/pt-br/contexto-data2021-03-30https://nullstack.app/pt-br/contexto-environment2021-03-30https://nullstack.app/pt-br/contexto-page2021-03-30https://nullstack.app/pt-br/contexto-project2021-03-30https://nullstack.app/pt-br/contexto-settings2021-03-30https://nullstack.app/pt-br/contexto-secrets2021-03-30https://nullstack.app/pt-br/instancia-self2021-03-30https://nullstack.app/pt-br/requisicao-e-resposta-do-servidor2021-03-30https://nullstack.app/pt-br/estilos2021-03-30https://nullstack.app/pt-br/extensao-de-arquivo-njs2021-03-30https://nullstack.app/pt-br/service-worker2021-03-30https://nullstack.app/pt-br/como-fazer-deploy-de-aplicacao-nullstack2021-03-30https://nullstack.app/pt-br/como-usar-mongodb-com-nullstack2021-03-30https://nullstack.app/pt-br/como-usar-google-analytics-no-nullstack2021-03-30https://nullstack.app/pt-br/como-usar-facebook-pixel-no-nullstack2021-03-30https://nullstack.app/pt-br/trabalhador-serviço2021-03-30https://nullstack.app/pt-br/extensão-de-arquivo-njs2021-03-30https://nullstack.app/pt-br/renderizacao-no-servidor2021-03-30https://nullstack.app/contexto-page2021-03-30https://nullstack.app/4042021-03-30 \ No newline at end of file diff --git a/docs/stateful-components.html b/docs/stateful-components.html deleted file mode 100644 index 3d63bc6d..00000000 --- a/docs/stateful-components.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - Stateful Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Stateful Components

A productive full-stack web framework should not force you to think about framework details.

-

Nullstack takes control of its subclasses and generates a proxy for each instance.

-

When you call anything on your class you are actually telling Nullstack what to do with the environment behind the scenes.

-

This allows you to use vanilla javascript operations like assigning to a variable and see the reflection in the dom.

-

Mutability

You can mutate instance variables to update your application state.

-

Functions are automatically bound to the instance proxy and can be passed as a reference to events.

-

Events are declared like normal HTML attributes.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment() {
-    this.count++;
-  }
-  
-  render() {
-    return (
-      <button onclick={this.increment}> 
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 Updates are made in batches, usually while awaiting async calls, so making multiple assignments have no performance costs!

-
-

Object Events

You can shortcut events that are simple assignments by passing an object to the event.

-

Each key of the object will be assigned to the instance.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-  
-  render() {
-    return (
-      <button onclick={{count: this.count + 1}}> 
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-

Event Source

By default, events refer to this when you pass an object.

-

You can use the source attribute to define which object will receive the assignments.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-  
-  render({params}) {
-    return (
-      <button source={params} onclick={{page: 1}}> 
-        First Page
-      </button>
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

✨ Learn more about context params.

-
-
-

💡 If you do not declare a source to the event, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

-
-

Event Context

Attributes of the event target will be merged to the instance context and can be destructured in the function signature.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment({delta}) {
-    this.count += delta;
-  }
-  
-  render() {
-    return (
-      <button onclick={this.increment} delta={2}> 
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 Any attribute with primitive value will be added to the DOM.

-
-
-

✨ Consider using data attributes to make your html valid.

-
-

Original Event

The browser default behavior is prevented by default.

-

You can opt-out of this by declaring a default attribute to the event element.

-

A reference to the original event is always merged with the function context.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  submit({event}) {
-    event.preventDefault();
-  }
-  
-  render() {
-    return (
-      <form onsubmit={this.submit} default>
-        <button> Submit </button>
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

Next steps

⚔ Learn about the full-stack lifecycle.

-
- - - \ No newline at end of file diff --git a/docs/stateful-components/index.html b/docs/stateful-components/index.html deleted file mode 100644 index 3d63bc6d..00000000 --- a/docs/stateful-components/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - Stateful Components - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Stateful Components

A productive full-stack web framework should not force you to think about framework details.

-

Nullstack takes control of its subclasses and generates a proxy for each instance.

-

When you call anything on your class you are actually telling Nullstack what to do with the environment behind the scenes.

-

This allows you to use vanilla javascript operations like assigning to a variable and see the reflection in the dom.

-

Mutability

You can mutate instance variables to update your application state.

-

Functions are automatically bound to the instance proxy and can be passed as a reference to events.

-

Events are declared like normal HTML attributes.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment() {
-    this.count++;
-  }
-  
-  render() {
-    return (
-      <button onclick={this.increment}> 
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 Updates are made in batches, usually while awaiting async calls, so making multiple assignments have no performance costs!

-
-

Object Events

You can shortcut events that are simple assignments by passing an object to the event.

-

Each key of the object will be assigned to the instance.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-  
-  render() {
-    return (
-      <button onclick={{count: this.count + 1}}> 
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-

Event Source

By default, events refer to this when you pass an object.

-

You can use the source attribute to define which object will receive the assignments.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-  
-  render({params}) {
-    return (
-      <button source={params} onclick={{page: 1}}> 
-        First Page
-      </button>
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

✨ Learn more about context params.

-
-
-

💡 If you do not declare a source to the event, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

-
-

Event Context

Attributes of the event target will be merged to the instance context and can be destructured in the function signature.

-
import Nullstack from 'nullstack';
-
-class Counter extends Nullstack {
-
-  count = 0;
-
-  increment({delta}) {
-    this.count += delta;
-  }
-  
-  render() {
-    return (
-      <button onclick={this.increment} delta={2}> 
-        {this.count}
-      </button>
-    )
-  }
-
-}
-
-export default Counter;
-
-
-

💡 Any attribute with primitive value will be added to the DOM.

-
-
-

✨ Consider using data attributes to make your html valid.

-
-

Original Event

The browser default behavior is prevented by default.

-

You can opt-out of this by declaring a default attribute to the event element.

-

A reference to the original event is always merged with the function context.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  submit({event}) {
-    event.preventDefault();
-  }
-  
-  render() {
-    return (
-      <form onsubmit={this.submit} default>
-        <button> Submit </button>
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

Next steps

⚔ Learn about the full-stack lifecycle.

-
- - - \ No newline at end of file diff --git a/docs/stateful-components/index.json b/docs/stateful-components/index.json deleted file mode 100644 index 2de19382..00000000 --- a/docs/stateful-components/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Stateful Components","html":"

A productive full-stack web framework should not force you to think about framework details.

\n

Nullstack takes control of its subclasses and generates a proxy for each instance.

\n

When you call anything on your class you are actually telling Nullstack what to do with the environment behind the scenes.

\n

This allows you to use vanilla javascript operations like assigning to a variable and see the reflection in the dom.

\n

Mutability

You can mutate instance variables to update your application state.

\n

Functions are automatically bound to the instance proxy and can be passed as a reference to events.

\n

Events are declared like normal HTML attributes.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  increment() {\n    this.count++;\n  }\n  \n  render() {\n    return (\n      <button onclick={this.increment}> \n        {this.count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
\n

💡 Updates are made in batches, usually while awaiting async calls, so making multiple assignments have no performance costs!

\n
\n

Object Events

You can shortcut events that are simple assignments by passing an object to the event.

\n

Each key of the object will be assigned to the instance.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n  \n  render() {\n    return (\n      <button onclick={{count: this.count + 1}}> \n        {this.count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n

Event Source

By default, events refer to this when you pass an object.

\n

You can use the source attribute to define which object will receive the assignments.

\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n  \n  render({params}) {\n    return (\n      <button source={params} onclick={{page: 1}}> \n        First Page\n      </button>\n    )\n  }\n\n}\n\nexport default Paginator;\n
\n
\n

✨ Learn more about context params.

\n
\n
\n

💡 If you do not declare a source to the event, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

\n
\n

Event Context

Attributes of the event target will be merged to the instance context and can be destructured in the function signature.

\n
import Nullstack from 'nullstack';\n\nclass Counter extends Nullstack {\n\n  count = 0;\n\n  increment({delta}) {\n    this.count += delta;\n  }\n  \n  render() {\n    return (\n      <button onclick={this.increment} delta={2}> \n        {this.count}\n      </button>\n    )\n  }\n\n}\n\nexport default Counter;\n
\n
\n

💡 Any attribute with primitive value will be added to the DOM.

\n
\n
\n

✨ Consider using data attributes to make your html valid.

\n
\n

Original Event

The browser default behavior is prevented by default.

\n

You can opt-out of this by declaring a default attribute to the event element.

\n

A reference to the original event is always merged with the function context.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  submit({event}) {\n    event.preventDefault();\n  }\n  \n  render() {\n    return (\n      <form onsubmit={this.submit} default>\n        <button> Submit </button>\n      </form>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Next steps

⚔ Learn about the full-stack lifecycle.

\n","description":"A productive full-stack web framework should not force you to think about framework details"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Stateful Components - Nullstack","description":"A productive full-stack web framework should not force you to think about framework details"}} \ No newline at end of file diff --git a/docs/static-site-generation.html b/docs/static-site-generation.html deleted file mode 100644 index 1bc04475..00000000 --- a/docs/static-site-generation.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - Static Site Generation - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Static Site Generation

Use Nullstack to generate static websites for lightning-fast static applications using the full power of the Nullstack client without the need for a node.js back-end.

-

Static sites are useful for read-only applications like blogs and documentation.

-
-

💡 This documentation is actually a static site generated with Nullstack.

-
-

All the benefits of server-side rendering apply to static generated sites.

-

You can generate a static website from your Nullstack application with the following npx command:

-
npx create-nullstatic-app
-
-
-

🔥 You must be in a Nullstack project folder to run this command.

-
-

By default, it will create your Nullstatic application in the static folder.

-

You can change the folder by passing it as an argument to the command:

-
npx create-nullstatic-app docs
-
-

The Nullstatic generator will run your application in production mode and crawl every link to an internal route it finds in your DOM.

-
-

💡 Make sure to have the server production port free when you run this command.

-
-

The manifest.json and the contents of the public folder will be copied into the target folder.

-

Besides generating raw HTML it will also generate a JSON file for each route with a copy of the state.

-

On the first visit to your static application, HTML will be served and hydrated.

-

On the subsequent requests, Nullstack will fetch the generated JSON and update the application state without ever reloading the page.

-

This, in fact, gives you not only a static generated site, but a static generated API that feeds a Single Page Application with zero costs.

-

Good Pratices

You can add a script to your package.json to generate your static website in a custom folder:

-
{
-  "name": "nullstack.github.io",
-  "version": "0.0.1",
-  "description": "",
-  "author": "",
-  "license": "ISC",
-  "devDependencies": {
-    "nullstack": "~0.9.0"
-  },
-  "scripts": {
-    "start": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=development --watch",
-    "build": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=production",
-    "ssg": "npx create-nullstatic-app docs"
-  }
-}
-
-
-

Caveats

Nullstatic only crawls your application up to the initiate resolution, further API requests triggered by events will be ignored.

-

Nullstatic will crawl a "/404" URL and generate both a "/404.html" and a "/404/index.html".

-

Next step

⚔ Learn more about the service worker.

-
- - - \ No newline at end of file diff --git a/docs/static-site-generation/index.html b/docs/static-site-generation/index.html deleted file mode 100644 index 1bc04475..00000000 --- a/docs/static-site-generation/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - Static Site Generation - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Static Site Generation

Use Nullstack to generate static websites for lightning-fast static applications using the full power of the Nullstack client without the need for a node.js back-end.

-

Static sites are useful for read-only applications like blogs and documentation.

-
-

💡 This documentation is actually a static site generated with Nullstack.

-
-

All the benefits of server-side rendering apply to static generated sites.

-

You can generate a static website from your Nullstack application with the following npx command:

-
npx create-nullstatic-app
-
-
-

🔥 You must be in a Nullstack project folder to run this command.

-
-

By default, it will create your Nullstatic application in the static folder.

-

You can change the folder by passing it as an argument to the command:

-
npx create-nullstatic-app docs
-
-

The Nullstatic generator will run your application in production mode and crawl every link to an internal route it finds in your DOM.

-
-

💡 Make sure to have the server production port free when you run this command.

-
-

The manifest.json and the contents of the public folder will be copied into the target folder.

-

Besides generating raw HTML it will also generate a JSON file for each route with a copy of the state.

-

On the first visit to your static application, HTML will be served and hydrated.

-

On the subsequent requests, Nullstack will fetch the generated JSON and update the application state without ever reloading the page.

-

This, in fact, gives you not only a static generated site, but a static generated API that feeds a Single Page Application with zero costs.

-

Good Pratices

You can add a script to your package.json to generate your static website in a custom folder:

-
{
-  "name": "nullstack.github.io",
-  "version": "0.0.1",
-  "description": "",
-  "author": "",
-  "license": "ISC",
-  "devDependencies": {
-    "nullstack": "~0.9.0"
-  },
-  "scripts": {
-    "start": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=development --watch",
-    "build": "npx webpack --config node_modules/nullstack/webpack.config.js --mode=production",
-    "ssg": "npx create-nullstatic-app docs"
-  }
-}
-
-
-

Caveats

Nullstatic only crawls your application up to the initiate resolution, further API requests triggered by events will be ignored.

-

Nullstatic will crawl a "/404" URL and generate both a "/404.html" and a "/404/index.html".

-

Next step

⚔ Learn more about the service worker.

-
- - - \ No newline at end of file diff --git a/docs/static-site-generation/index.json b/docs/static-site-generation/index.json deleted file mode 100644 index 1d83faa3..00000000 --- a/docs/static-site-generation/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Static Site Generation","html":"

Use Nullstack to generate static websites for lightning-fast static applications using the full power of the Nullstack client without the need for a node.js back-end.

\n

Static sites are useful for read-only applications like blogs and documentation.

\n
\n

💡 This documentation is actually a static site generated with Nullstack.

\n
\n

All the benefits of server-side rendering apply to static generated sites.

\n

You can generate a static website from your Nullstack application with the following npx command:

\n
npx create-nullstatic-app\n
\n
\n

🔥 You must be in a Nullstack project folder to run this command.

\n
\n

By default, it will create your Nullstatic application in the static folder.

\n

You can change the folder by passing it as an argument to the command:

\n
npx create-nullstatic-app docs\n
\n

The Nullstatic generator will run your application in production mode and crawl every link to an internal route it finds in your DOM.

\n
\n

💡 Make sure to have the server production port free when you run this command.

\n
\n

The manifest.json and the contents of the public folder will be copied into the target folder.

\n

Besides generating raw HTML it will also generate a JSON file for each route with a copy of the state.

\n

On the first visit to your static application, HTML will be served and hydrated.

\n

On the subsequent requests, Nullstack will fetch the generated JSON and update the application state without ever reloading the page.

\n

This, in fact, gives you not only a static generated site, but a static generated API that feeds a Single Page Application with zero costs.

\n

Good Pratices

You can add a script to your package.json to generate your static website in a custom folder:

\n
{\n  \"name\": \"nullstack.github.io\",\n  \"version\": \"0.0.1\",\n  \"description\": \"\",\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"nullstack\": \"~0.9.0\"\n  },\n  \"scripts\": {\n    \"start\": \"npx webpack --config node_modules/nullstack/webpack.config.js --mode=development --watch\",\n    \"build\": \"npx webpack --config node_modules/nullstack/webpack.config.js --mode=production\",\n    \"ssg\": \"npx create-nullstatic-app docs\"\n  }\n}\n\n
\n

Caveats

Nullstatic only crawls your application up to the initiate resolution, further API requests triggered by events will be ignored.

\n

Nullstatic will crawl a "/404" URL and generate both a "/404.html" and a "/404/index.html".

\n

Next step

⚔ Learn more about the service worker.

\n","description":"Use Nullstack to generate static websites for lightning-fast static applications using the full power of Nullstack without the need for a node.js back-end"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Static Site Generation - Nullstack","description":"Use Nullstack to generate static websites for lightning-fast static applications using the full power of Nullstack without the need for a node.js back-end"}} \ No newline at end of file diff --git a/docs/styles.html b/docs/styles.html deleted file mode 100644 index a481acda..00000000 --- a/docs/styles.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - Styles - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Styles

Using styles with Nullstack is as simple as importing a style file.

-

Nullstack comes with a SASS loader by default, but you can still use vanilla CSS.

-
-

✨ It's a good practice to import a file with the same name as the component.

-
-
import Nullstack from 'nullstack';
-import './Header.scss';
-
-class Header extends Nullstack {
-  // ...
-}
-
-export default Header;
-
-

In production mode Nullstack uses PurceCSS, which cleans your client.css file, but has some gotchas.

-
-

✨ Learn more about safelisting your css

-
-

Next step

⚔ Learn about the NJS file extension.

-
- - - \ No newline at end of file diff --git a/docs/styles/index.html b/docs/styles/index.html deleted file mode 100644 index a481acda..00000000 --- a/docs/styles/index.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - Styles - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Styles

Using styles with Nullstack is as simple as importing a style file.

-

Nullstack comes with a SASS loader by default, but you can still use vanilla CSS.

-
-

✨ It's a good practice to import a file with the same name as the component.

-
-
import Nullstack from 'nullstack';
-import './Header.scss';
-
-class Header extends Nullstack {
-  // ...
-}
-
-export default Header;
-
-

In production mode Nullstack uses PurceCSS, which cleans your client.css file, but has some gotchas.

-
-

✨ Learn more about safelisting your css

-
-

Next step

⚔ Learn about the NJS file extension.

-
- - - \ No newline at end of file diff --git a/docs/styles/index.json b/docs/styles/index.json deleted file mode 100644 index 6f70e839..00000000 --- a/docs/styles/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Styles","html":"

Using styles with Nullstack is as simple as importing a style file.

\n

Nullstack comes with a SASS loader by default, but you can still use vanilla CSS.

\n
\n

✨ It's a good practice to import a file with the same name as the component.

\n
\n
import Nullstack from 'nullstack';\nimport './Header.scss';\n\nclass Header extends Nullstack {\n  // ...\n}\n\nexport default Header;\n
\n

In production mode Nullstack uses PurceCSS, which cleans your client.css file, but has some gotchas.

\n
\n

✨ Learn more about safelisting your css

\n
\n

Next step

⚔ Learn about the NJS file extension.

\n","description":"Using styles with Nullstack is as simple as importing a style file"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Styles - Nullstack","description":"Using styles with Nullstack is as simple as importing a style file"}} \ No newline at end of file diff --git a/docs/thumbnail-en-us-1.webp b/docs/thumbnail-en-us-1.webp deleted file mode 100644 index 63a124f1..00000000 Binary files a/docs/thumbnail-en-us-1.webp and /dev/null differ diff --git a/docs/thumbnail-en-us-2.webp b/docs/thumbnail-en-us-2.webp deleted file mode 100644 index 74cd6e31..00000000 Binary files a/docs/thumbnail-en-us-2.webp and /dev/null differ diff --git a/docs/thumbnail-en-us-3.webp b/docs/thumbnail-en-us-3.webp deleted file mode 100644 index 8d9bd111..00000000 Binary files a/docs/thumbnail-en-us-3.webp and /dev/null differ diff --git a/docs/thumbnail-pt-br-1.webp b/docs/thumbnail-pt-br-1.webp deleted file mode 100644 index f924404e..00000000 Binary files a/docs/thumbnail-pt-br-1.webp and /dev/null differ diff --git a/docs/thumbnail-pt-br-2.webp b/docs/thumbnail-pt-br-2.webp deleted file mode 100644 index 2c1272a7..00000000 Binary files a/docs/thumbnail-pt-br-2.webp and /dev/null differ diff --git a/docs/thumbnail-pt-br-3.webp b/docs/thumbnail-pt-br-3.webp deleted file mode 100644 index a9b32939..00000000 Binary files a/docs/thumbnail-pt-br-3.webp and /dev/null differ diff --git a/docs/two-way-bindings.html b/docs/two-way-bindings.html deleted file mode 100644 index 91f529f3..00000000 --- a/docs/two-way-bindings.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - Two-Way Binding - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Two-Way Binding

Big chunks of code in a progressive web application is dedicated to reacting to user input.

-

The process of controlling user input can be broken into 3 tedious steps:

-
    -
  • Declaring a variable with the initial value;
  • -
  • Passing the initial value to the input;
  • -
  • Observing changes in the input and assigning the new value to the variable.
  • -
-

The last step might include typecasting and other value treatments.

-

This process in which you manually do all these steps is called one-way binding, it is the default in many frameworks, and is possible in Nullstack.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
-
-  updateString({event}) {
-    this.string = event.target.value;
-  }
-
-  updateNumber({event}) {
-    this.number = parseInt(event.target.value);
-  }
- 
-  render() {
-    return (
-      <form>
-        <input
-          type="text"
-          name="string"
-          value={this.string}
-          oninput={this.updateString}
-        />
-        <input
-          type="number"
-          name="number"
-          value={this.number}
-          oninput={this.updateNumber}
-        />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

The bind attribute

Bind reduces drastically the amount of glue code you have to type in your application.

-

You can shortcut setting a value, name, and event with the bind attribute.

-
-

💡 Nullstack will simply replace bind with the value, name, and event under the hood.

-
-

Bind will generate an event that automatically typecasts to the previous primitive type the value was.

-

You can pass any variable to the bind as long as its parent object is mentioned.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
- 
-  render() {
-    return (
-      <form>
-        <input type="text" bind={this.string} />
-        <input type="number" bind={this.number} />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

Bound Events

The following events are set for each type of input:

-
    -
  • onclick for inputs with the checkbox type
  • -
  • oninput for other inputs and textareas
  • -
  • onchange for anything else
  • -
-

You can still declare an attribute with the same bound event.

-

Events will not override the bound event, instead, it will be executed after bind mutates the variable.

-

The new value will be merged into the function context.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  name = '';
-
-  compare({value}) {
-    this.name === value;
-  }
- 
-  render() {
-    return (
-      <input bind={this.name} oninput={this.compare} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Bind source

Bind can take a source attribute as well.

-
-

💡 If you do not declare a source to the bind, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

-
-

If you declare a source, bind must be a string with the name of the key that will be mutated.

-

The source will be merged into the context of events.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  validate({source, params}) {
-    if(!source.page) {
-      params.page = '1';
-    }
-  }
-
-  render({params}) {
-    return (
-      <input 
-        source={params}
-        bind="page"
-        oninput={this.validate}
-      />
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

💡 Binding by reference is possible because all binds are converted to the format above at transpile time.

-
-

Any object that responds to a key call with "[]" can be bound.

-

The name attribute can be overwritten.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  character = 'a';
-  text = 'aaaa';
-  
-  object = {count: 1};
-  array = ['a', 'b', 'c'];
-
-  render({params}) {
-    return (
-      <div>
-        <input bind={this.number} />
-        <textarea bind={this.text} />
-        <select bind={this.character}>
-          {this.array.map((character) => <option>{character}</option>)}
-        </select>
-        <select bind={this.boolean} name="boolean-select">
-          <option value={true}>true</option>
-          <option value={false}>false</option>
-        </select>
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.count} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </div>
-    )
-  }
-
-}
-
-export default Form;
-
-

Object Events

You can use object events alongside bind normally.

-

The event will run after the variable is mutated.

-

The event will share the bind source.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  render({params}) {
-    return (
-      <input bind={params.filter} oninput={{page: 1}} />
-    )
-  }
-
-}
-
-export default Paginator;
-
-

Bindable Components

You can create your own bindable component by receiving the attributes that bind generates.

-

You must respond by calling onchange with a value key.

-

You can also merge any other keys you wish to send to the component user.

-
class CurrencyInput extends Nullstack {
-
-  parse({event, onchange}) {
-    const normalized = event.target.value.replace(',', '').padStart(3, '0');
-    const whole = (parseInt(normalized.slice(0,-2)) || 0).toString();
-    const decimal = normalized.slice(normalized.length - 2);
-    const value = parseFloat(whole+'.'+decimal);
-    const bringsHappyness = value >= 1000000;
-    onchange({value, bringsHappyness});
-  }
-
-  render({value, name}) {
-    const formatted = value.toFixed(2).replace('.', ',');
-    return <input name={name} value={formatted} oninput={this.parse} />
-  }
-
-}
-
-
import Nullstack from 'nullstack';
-import CurrencyInput from './CurrencyInput';
-
-class Form extends Nullstack {
-
-  balance = 0;
-
-  render() {
-    return (
-      <CurrencyInput bind={this.balance} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Next step

-

🎉 Congratulations!. You are done with the core concepts!

-
-

⚔ Learn about the application startup.

-
- - - \ No newline at end of file diff --git a/docs/two-way-bindings/index.html b/docs/two-way-bindings/index.html deleted file mode 100644 index 91f529f3..00000000 --- a/docs/two-way-bindings/index.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - Two-Way Binding - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -

Two-Way Binding

Big chunks of code in a progressive web application is dedicated to reacting to user input.

-

The process of controlling user input can be broken into 3 tedious steps:

-
    -
  • Declaring a variable with the initial value;
  • -
  • Passing the initial value to the input;
  • -
  • Observing changes in the input and assigning the new value to the variable.
  • -
-

The last step might include typecasting and other value treatments.

-

This process in which you manually do all these steps is called one-way binding, it is the default in many frameworks, and is possible in Nullstack.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
-
-  updateString({event}) {
-    this.string = event.target.value;
-  }
-
-  updateNumber({event}) {
-    this.number = parseInt(event.target.value);
-  }
- 
-  render() {
-    return (
-      <form>
-        <input
-          type="text"
-          name="string"
-          value={this.string}
-          oninput={this.updateString}
-        />
-        <input
-          type="number"
-          name="number"
-          value={this.number}
-          oninput={this.updateNumber}
-        />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

The bind attribute

Bind reduces drastically the amount of glue code you have to type in your application.

-

You can shortcut setting a value, name, and event with the bind attribute.

-
-

💡 Nullstack will simply replace bind with the value, name, and event under the hood.

-
-

Bind will generate an event that automatically typecasts to the previous primitive type the value was.

-

You can pass any variable to the bind as long as its parent object is mentioned.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  string = '';
- 
-  render() {
-    return (
-      <form>
-        <input type="text" bind={this.string} />
-        <input type="number" bind={this.number} />
-      </form>
-    )
-  }
-
-}
-
-export default Form;
-
-

Bound Events

The following events are set for each type of input:

-
    -
  • onclick for inputs with the checkbox type
  • -
  • oninput for other inputs and textareas
  • -
  • onchange for anything else
  • -
-

You can still declare an attribute with the same bound event.

-

Events will not override the bound event, instead, it will be executed after bind mutates the variable.

-

The new value will be merged into the function context.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  name = '';
-
-  compare({value}) {
-    this.name === value;
-  }
- 
-  render() {
-    return (
-      <input bind={this.name} oninput={this.compare} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Bind source

Bind can take a source attribute as well.

-
-

💡 If you do not declare a source to the bind, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

-
-

If you declare a source, bind must be a string with the name of the key that will be mutated.

-

The source will be merged into the context of events.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  validate({source, params}) {
-    if(!source.page) {
-      params.page = '1';
-    }
-  }
-
-  render({params}) {
-    return (
-      <input 
-        source={params}
-        bind="page"
-        oninput={this.validate}
-      />
-    )
-  }
-
-}
-
-export default Paginator;
-
-
-

💡 Binding by reference is possible because all binds are converted to the format above at transpile time.

-
-

Any object that responds to a key call with "[]" can be bound.

-

The name attribute can be overwritten.

-
import Nullstack from 'nullstack';
-
-class Form extends Nullstack {
-
-  number = 1;
-  boolean = true;
-  character = 'a';
-  text = 'aaaa';
-  
-  object = {count: 1};
-  array = ['a', 'b', 'c'];
-
-  render({params}) {
-    return (
-      <div>
-        <input bind={this.number} />
-        <textarea bind={this.text} />
-        <select bind={this.character}>
-          {this.array.map((character) => <option>{character}</option>)}
-        </select>
-        <select bind={this.boolean} name="boolean-select">
-          <option value={true}>true</option>
-          <option value={false}>false</option>
-        </select>
-        <input bind={this.boolean} type="checkbox" />
-        <input bind={this.object.count} />
-        {this.array.map((value, index) => (
-          <input bind={this.array[index]} />
-        ))}
-        <input bind={params.page} />
-      </div>
-    )
-  }
-
-}
-
-export default Form;
-
-

Object Events

You can use object events alongside bind normally.

-

The event will run after the variable is mutated.

-

The event will share the bind source.

-
import Nullstack from 'nullstack';
-
-class Paginator extends Nullstack {
-
-  render({params}) {
-    return (
-      <input bind={params.filter} oninput={{page: 1}} />
-    )
-  }
-
-}
-
-export default Paginator;
-
-

Bindable Components

You can create your own bindable component by receiving the attributes that bind generates.

-

You must respond by calling onchange with a value key.

-

You can also merge any other keys you wish to send to the component user.

-
class CurrencyInput extends Nullstack {
-
-  parse({event, onchange}) {
-    const normalized = event.target.value.replace(',', '').padStart(3, '0');
-    const whole = (parseInt(normalized.slice(0,-2)) || 0).toString();
-    const decimal = normalized.slice(normalized.length - 2);
-    const value = parseFloat(whole+'.'+decimal);
-    const bringsHappyness = value >= 1000000;
-    onchange({value, bringsHappyness});
-  }
-
-  render({value, name}) {
-    const formatted = value.toFixed(2).replace('.', ',');
-    return <input name={name} value={formatted} oninput={this.parse} />
-  }
-
-}
-
-
import Nullstack from 'nullstack';
-import CurrencyInput from './CurrencyInput';
-
-class Form extends Nullstack {
-
-  balance = 0;
-
-  render() {
-    return (
-      <CurrencyInput bind={this.balance} />
-    )
-  }
-
-}
-
-export default Form;
-
-

Next step

-

🎉 Congratulations!. You are done with the core concepts!

-
-

⚔ Learn about the application startup.

-
- - - \ No newline at end of file diff --git a/docs/two-way-bindings/index.json b/docs/two-way-bindings/index.json deleted file mode 100644 index a1317ef4..00000000 --- a/docs/two-way-bindings/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Two-Way Binding","html":"

Big chunks of code in a progressive web application is dedicated to reacting to user input.

\n

The process of controlling user input can be broken into 3 tedious steps:

\n
    \n
  • Declaring a variable with the initial value;
  • \n
  • Passing the initial value to the input;
  • \n
  • Observing changes in the input and assigning the new value to the variable.
  • \n
\n

The last step might include typecasting and other value treatments.

\n

This process in which you manually do all these steps is called one-way binding, it is the default in many frameworks, and is possible in Nullstack.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  number = 1;\n  string = '';\n\n  updateString({event}) {\n    this.string = event.target.value;\n  }\n\n  updateNumber({event}) {\n    this.number = parseInt(event.target.value);\n  }\n \n  render() {\n    return (\n      <form>\n        <input\n          type=\"text\"\n          name=\"string\"\n          value={this.string}\n          oninput={this.updateString}\n        />\n        <input\n          type=\"number\"\n          name=\"number\"\n          value={this.number}\n          oninput={this.updateNumber}\n        />\n      </form>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

The bind attribute

Bind reduces drastically the amount of glue code you have to type in your application.

\n

You can shortcut setting a value, name, and event with the bind attribute.

\n
\n

💡 Nullstack will simply replace bind with the value, name, and event under the hood.

\n
\n

Bind will generate an event that automatically typecasts to the previous primitive type the value was.

\n

You can pass any variable to the bind as long as its parent object is mentioned.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  number = 1;\n  string = '';\n \n  render() {\n    return (\n      <form>\n        <input type=\"text\" bind={this.string} />\n        <input type=\"number\" bind={this.number} />\n      </form>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Bound Events

The following events are set for each type of input:

\n
    \n
  • onclick for inputs with the checkbox type
  • \n
  • oninput for other inputs and textareas
  • \n
  • onchange for anything else
  • \n
\n

You can still declare an attribute with the same bound event.

\n

Events will not override the bound event, instead, it will be executed after bind mutates the variable.

\n

The new value will be merged into the function context.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  name = '';\n\n  compare({value}) {\n    this.name === value;\n  }\n \n  render() {\n    return (\n      <input bind={this.name} oninput={this.compare} />\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Bind source

Bind can take a source attribute as well.

\n
\n

💡 If you do not declare a source to the bind, Nullstack will inject a source={this} at transpile time in order to completely skip the runtime lookup process!

\n
\n

If you declare a source, bind must be a string with the name of the key that will be mutated.

\n

The source will be merged into the context of events.

\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n\n  validate({source, params}) {\n    if(!source.page) {\n      params.page = '1';\n    }\n  }\n\n  render({params}) {\n    return (\n      <input \n        source={params}\n        bind=\"page\"\n        oninput={this.validate}\n      />\n    )\n  }\n\n}\n\nexport default Paginator;\n
\n
\n

💡 Binding by reference is possible because all binds are converted to the format above at transpile time.

\n
\n

Any object that responds to a key call with "[]" can be bound.

\n

The name attribute can be overwritten.

\n
import Nullstack from 'nullstack';\n\nclass Form extends Nullstack {\n\n  number = 1;\n  boolean = true;\n  character = 'a';\n  text = 'aaaa';\n  \n  object = {count: 1};\n  array = ['a', 'b', 'c'];\n\n  render({params}) {\n    return (\n      <div>\n        <input bind={this.number} />\n        <textarea bind={this.text} />\n        <select bind={this.character}>\n          {this.array.map((character) => <option>{character}</option>)}\n        </select>\n        <select bind={this.boolean} name=\"boolean-select\">\n          <option value={true}>true</option>\n          <option value={false}>false</option>\n        </select>\n        <input bind={this.boolean} type=\"checkbox\" />\n        <input bind={this.object.count} />\n        {this.array.map((value, index) => (\n          <input bind={this.array[index]} />\n        ))}\n        <input bind={params.page} />\n      </div>\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Object Events

You can use object events alongside bind normally.

\n

The event will run after the variable is mutated.

\n

The event will share the bind source.

\n
import Nullstack from 'nullstack';\n\nclass Paginator extends Nullstack {\n\n  render({params}) {\n    return (\n      <input bind={params.filter} oninput={{page: 1}} />\n    )\n  }\n\n}\n\nexport default Paginator;\n
\n

Bindable Components

You can create your own bindable component by receiving the attributes that bind generates.

\n

You must respond by calling onchange with a value key.

\n

You can also merge any other keys you wish to send to the component user.

\n
class CurrencyInput extends Nullstack {\n\n  parse({event, onchange}) {\n    const normalized = event.target.value.replace(',', '').padStart(3, '0');\n    const whole = (parseInt(normalized.slice(0,-2)) || 0).toString();\n    const decimal = normalized.slice(normalized.length - 2);\n    const value = parseFloat(whole+'.'+decimal);\n    const bringsHappyness = value >= 1000000;\n    onchange({value, bringsHappyness});\n  }\n\n  render({value, name}) {\n    const formatted = value.toFixed(2).replace('.', ',');\n    return <input name={name} value={formatted} oninput={this.parse} />\n  }\n\n}\n
\n
import Nullstack from 'nullstack';\nimport CurrencyInput from './CurrencyInput';\n\nclass Form extends Nullstack {\n\n  balance = 0;\n\n  render() {\n    return (\n      <CurrencyInput bind={this.balance} />\n    )\n  }\n\n}\n\nexport default Form;\n
\n

Next step

\n

🎉 Congratulations!. You are done with the core concepts!

\n
\n

⚔ Learn about the application startup.

\n","description":"Bind reduces drastically the amount of glue code you have to type in your application."},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Two-Way Binding - Nullstack","description":"Bind reduces drastically the amount of glue code you have to type in your application."}} \ No newline at end of file diff --git a/docs/waifu.html b/docs/waifu.html deleted file mode 100644 index b4435386..00000000 --- a/docs/waifu.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Nulla-Chan - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nulla-Chan

Nulla - Chan

Nullstack's official waifu

  • 🕐 Age: 19
  • ♒ Sign: Aquarius
  • 🎂 Birthday: January 28
  • 💖 Blood Type: A
  • 📏 Height: 1.55m
  • 🍨 Fav Food: Anything vanilla flavored
  • 🧩 Hobby: Reinventing Wheels
  • 🧠 Neurodivergences: ASD and ADHD
🎨 Created by: Bilkaya Check out the Character Concept

A sweet and shy perfect waifu, is always hyperfocused in her studies but somehow distracted at the same time.

She is always cheerful... until she has to face glue code or sees a post telling her which tech she should use.

- - - \ No newline at end of file diff --git a/docs/waifu.png b/docs/waifu.png deleted file mode 100644 index 2154b9b7..00000000 Binary files a/docs/waifu.png and /dev/null differ diff --git a/docs/waifu/index.html b/docs/waifu/index.html deleted file mode 100644 index b4435386..00000000 --- a/docs/waifu/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - Nulla-Chan - Nullstack - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nulla-Chan

Nulla - Chan

Nullstack's official waifu

  • 🕐 Age: 19
  • ♒ Sign: Aquarius
  • 🎂 Birthday: January 28
  • 💖 Blood Type: A
  • 📏 Height: 1.55m
  • 🍨 Fav Food: Anything vanilla flavored
  • 🧩 Hobby: Reinventing Wheels
  • 🧠 Neurodivergences: ASD and ADHD
🎨 Created by: Bilkaya Check out the Character Concept

A sweet and shy perfect waifu, is always hyperfocused in her studies but somehow distracted at the same time.

She is always cheerful... until she has to face glue code or sees a post telling her which tech she should use.

- - - \ No newline at end of file diff --git a/docs/waifu/index.json b/docs/waifu/index.json deleted file mode 100644 index 25671ea8..00000000 --- a/docs/waifu/index.json +++ /dev/null @@ -1 +0,0 @@ -{"instances": {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-9":{"locale":"en-US","i18n":{"title":"Nulla-Chan","description":"Nullstack's official waifu","tagline":"Nullstack's official waifu","attributes":[{"label":"🕐 Age","value":"19"},{"label":"♒ Sign","value":"Aquarius"},{"label":"🎂 Birthday","value":"January 28"},{"label":"💖 Blood Type","value":"A"},{"label":"📏 Height","value":"1.55m"},{"label":"🍨 Fav Food","value":"Anything vanilla flavored"},{"label":"🧩 Hobby","value":"Reinventing Wheels"},{"label":"🧠 Neurodivergences","value":"ASD and ADHD"}],"artist":{"label":"🎨 Created by:","href":"https://www.instagram.com/biancazanette","text":"Bilkaya"},"concept":{"label":"Check out the","href":"https://www.artstation.com/artwork/Vg4o6R","text":"Character Concept"},"descriptions":["A sweet and shy perfect waifu, is always hyperfocused in her studies but somehow distracted at the same time.","She is always cheerful... until she has to face glue code or sees a post telling her which tech she should use."]}},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}}, "page": {"image":"/image-1200x630.png","status":200,"title":"Nulla-Chan - Nullstack","description":"Nullstack's official waifu","locale":"en-US"}} \ No newline at end of file diff --git a/i18n/en-US/articles/about.md b/i18n/en-US/articles/about.md deleted file mode 100644 index c553a0e8..00000000 --- a/i18n/en-US/articles/about.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Why Nullstack Exists -description: The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application ---- - -The sole purpose of Nullstack is to simplify the development by eliminating glue code and letting you focus on the logic of your application. - -It was created keeping in mind programmers used to developing entire systems alone, but it is easily scalable to small or even big teams, as long as each programmer knows the flow of the feature they are to develop. - -## The Stack - -With the stack of technologies used in the web nowadays, the most common flow is something like this: - -- Front-end uses a reducer over a context that calls a fetcher; -- This fetcher brings generic information over a RESTful API; -- The RESTful API calls a server route, which calls a controller, which takes the information of a model and resolves it into a serializer; -- If you need more than one resource, this process should be repeated until all resources are fetched; -- After all the data has been fetched, only then should the front-end be able to use it; -- Reason about how to deal with server-side render and hydration of the steps above; - -Note that all you wanted was to show something from the database into a view. With Nullstack, that’s all you need to concern yourself with. Everything else is “glue code” and the framework should take care of it for you. - -## Feature-driven - -If you’re used to working on more than one project at a time or even if you just happen to have to give sporadic maintenance to a lot of your old projects, you might have stumbled upon this scenario: you don’t remember exactly where in your code is the logic you’re trying to fix or improve. - -You might have a hook whose dependencies are local variables initialized with a redux state, which was stored at some point by an action declared somewhere in your source tree and called in who knows where. - -If everything pertaining to a single feature were to be in the same file, maybe you wouldn’t need to reverse engineer your own code every time you need to update or fix something. - -Putting everything in a single file may sound messy at a glance, but remember that you are the one who decides the granularity of this division. - -A "feature" might be an entire register form or something as small as a button that does some verifications before letting you submit that form. It’s entirely up to you, and since each component is as complete as an entire feature, you could call this button or even the entire form on other pages in your application. This leads us to **True Componentization and Code Reusability**. - -## Componentization and Code Reusability - -Components in Nullstack are self-sufficient. - -Most frameworks are specialized in a single layer, meaning that any component will be only as complete as its framework. When exporting a Nullstack component, all the code needed to run the feature is going to be together, without the need of allocating the other layers separately. - -As a side effect, entire applications can be used as components, and mounted in other applications as engines. - -## Why object-oriented instead of functional - -At first glance, classes may look more verbose than the trendy functional components. -This section will explain the reasons that lead us to favor classes in the development of Nullstack. - -The reasons are actually connected to some core principles of Nullstack, being: - -### Everything as Vanilla as Possible - -We didn’t want to introduce a “Nullstack way” of doing things and wanted it to be accessible to anyone with some Javascript knowledge. - -That being said, the first big problem was to address state management in a vanilla Javascript way. Supporting functional components would require a solution similar to the hooks of React.js that would be considered a mannerism of the framework. - -Since we opted out of immutability as a framework constraint, we are allowed to use the native way of setting simple variables. This removes the complexity of state management that created the need of third-party state management libraries in the first place. - -### No Glue Code or “Batteries Included” - -Nullstack borrows the concept of “battery-included” from Ember.js, but allows you to change batteries. Everything you need to make an application should be part of the framework, and still be flexible. - -A framework should do the heavy lifting and a programmer should focus on his own application. -For this reason, all you have to do is to declare your classes and let Nullstack instantiate them for you. That way, we removed the most painful aspect of dealing with classes while maintaining all of the advantages of them. - -### Having a safe escape route - -Object-oriented versus functional is not a new topic, and lately the former seems to be bullied out of most frameworks, leaving no place for developers that enjoy this pattern. - -Admittedly classes took too long to be standardized into Javascript and the delay might have caused some traumatic bad implementations along the way. - -While object-oriented programming might not be the best solution for every problem, Nullstack allows you to import functions freely and use them in the moments when they should be the weapon of choice. - -## Why dependency injection instead of modularity - -Nullstack context uses the dependency injection pattern, which means that everything you need can be requested from the framework at the signature level of the function. - -The context is a horizontally scoped object that is injected in all of your function calls. The non-hierarchical nature of this pattern allows you to easily move around your component's logic as your application grows, while still avoiding problems like props drilling or filling your view layer with store declarations. - -This has two major advantages: - -- You see the dependencies of your code at a function level instead of having them all imported on top of the file. - -- The framework is able to give you the most precise information about the specific environment for that function call. - -## Developer Happiness - -The generated application is enough to have a PWA without thinking about boilerplates, but you are completely free to override the default behavior of each moving piece. - -A borrowed concept from Ruby is developer happiness. Nullstack aims to ease the developer’s life by simplifying everything possible, but without hiding things from you. - -The first developers we wanted to make happy are ourselves. We made Nullstack because we had fun in the process. It started as a simple prototype on top of React.js and we got carried away, each time making it more enjoyable for us until it became its own thing. - -We hope you enjoy using Nullstack as much as we do because that's what keeps this project going forward. diff --git a/i18n/en-US/articles/application-startup.md b/i18n/en-US/articles/application-startup.md index 65411937..c1c03a98 100644 --- a/i18n/en-US/articles/application-startup.md +++ b/i18n/en-US/articles/application-startup.md @@ -1,50 +1,65 @@ --- title: Application Startup -description: The start function will run only once when your application is booted and is a good place for setting up your server context +description: The start function will run only once when your application loads and is a good place for setting up your context +action: ⚔ Learn about the [application startup](/application-startup). --- -The **index.js** file at your application root is responsible for starting your application. +The **server.js**/**client.js** files at your application root are responsible for starting your application. -When you run the application with `npm start` or `node .production/server.js` the **index** will call the `start` function in your **src/Application.js**. +When you run the application with `npm start` the `Nullstack.start` method in both files will start your main component and return the [`context`](/context) object of their respectives environments. -The `start` function will run only once when your application is booted and is a good place for setting up your [server context](/context). +The returned `context` could be used normally, and you can set it's `start` method which runs only once, being a good place for setting things up, as your database: ```jsx import Nullstack from 'nullstack'; -import database from './database'; +import Application from './src/Application'; +import startDatabase from './database'; -class Application extends Nullstack { - - static async start(context) { - context.database = database; - } +const context = Nullstack.start(Application); +context.start = async function() { + context.database = await startDatabase(context.secrets); } -export default Application; +export default context; ``` +> 💡 The `context.start` in **server.js** runs when the application is booted, and on **client.js** once the browser loads it + +The `context` can be updated in any way as long as it be exported on both files, when building the app Nullstack turns it into a serverless function out-of-box. + ## Dependency startup pattern -A nice pattern to work with dependencies that require startup time configurations is to define a `start` function in the dependency and call it in the Application `start` function passing the [server context](/context). +A nice pattern to work with dependencies that require startup time configurations is to define a `_start` function in the dependency: ```jsx import Nullstack from 'nullstack'; -import Dependency from './Dependency'; -class Application extends Nullstack { +class Dependency extends Nullstack { - static async start(context) { - Dependency.start(context); + static async _start(context) { + // start something with context } } -export default Application; +export default Dependency; ``` -> 🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding. +And call it in the `context.start` passing the [context](/context): + +```jsx +import Nullstack from 'nullstack'; +import Application from './src/Application'; +import Dependency from './src/Dependency'; -## Next step +const context = Nullstack.start(Application); + +context.start = async function() { + await Dependency._start(context); +} + +export default Application; +``` -⚔ Learn about the [context `data`](/context-data). \ No newline at end of file +> 🔒 Server functions with the name starting with "_" do not generate an API endpoint to avoid malicious API calls. \ No newline at end of file diff --git a/i18n/en-US/articles/context-data.md b/i18n/en-US/articles/context-data.md index 95c76648..28a49c8d 100644 --- a/i18n/en-US/articles/context-data.md +++ b/i18n/en-US/articles/context-data.md @@ -14,9 +14,7 @@ You can use this key to avoid polluting your DOM with invalid attributes. > 💡 This helps Nullstack set attributes without wasting time validating them. -Any `data-*` attributes will receive a respective camelized key on the `data` object. - -You can assign `data` attributes both via `data-*` and a `data` key that accepts an object with camelized keys. +Any `data-*` attributes will receive a respective camelized key on the `data` object when passed to an event context. The kebab version is also available in the context. @@ -30,17 +28,6 @@ class ContextData extends Nullstack { calculate({data}) { this.count = this.count * data.multiply + data.sum; } - - renderInner(context) { - const {data} = context; - return ( -
- {data.frameworkName} - is same as - {context['data-framework-name']} -
- ) - } render({data}) { return ( @@ -48,7 +35,6 @@ class ContextData extends Nullstack { - ) } @@ -58,8 +44,4 @@ class ContextData extends Nullstack { export default ContextData; ``` -> 💡 Camelized keys from the `data` object will result in kebab attributes in the DOM. - -## Next step - -⚔ Learn about the [context `environment`](/context-environment). \ No newline at end of file +> 💡 Camelized keys from the `data` object will result in kebab attributes in the DOM. \ No newline at end of file diff --git a/i18n/en-US/articles/context-environment.md b/i18n/en-US/articles/context-environment.md index d59ba1ce..b9ab3c59 100644 --- a/i18n/en-US/articles/context-environment.md +++ b/i18n/en-US/articles/context-environment.md @@ -18,6 +18,7 @@ The following keys are available in the object: - **production**: `boolean` - **static**: `boolean` - **key**: `string` +- **hot** `boolean` ```jsx import Nullstack from 'nullstack'; @@ -44,6 +45,27 @@ export default Page; The environment *key* is an md5 hash of the current environment folder outputs. The key is appended to [assets](/styles) and [static API](/static-site-generation) path to assist cache control. -## Next step +The environment *hot* is boolean that identifies if hot reload is enabled and is available only in development mode. -⚔ Learn about the [context `page`](/context-page). \ No newline at end of file +## Custom Events + +During development any updates to tracked files will raise a custom event you can use to facilitate development flow. + +You can use this event to improve the developer experience by creating custom side effects to changes, like reinitiating specific components that need to reload data when code changes. + +```jsx +import Nullstack from 'nullstack'; + +class BlogArticle extends Nullstack { + + hydrate({environment}) { + if(!environment.hot) return + window.addEventListener(environment.event, () => this.initiate()); + } + +} + +export default BlogArticle; +``` + +> 🔥 `environment.event` is only available in client functions/lifecycles. \ No newline at end of file diff --git a/i18n/en-US/articles/context-instances.md b/i18n/en-US/articles/context-instances.md new file mode 100644 index 00000000..932412f2 --- /dev/null +++ b/i18n/en-US/articles/context-instances.md @@ -0,0 +1,93 @@ +--- +title: Context Instances +description: The instances object is a proxy in the Nullstack Context available in the client and gives you all active instances in the application +--- + +- Type: `object` +- Origin: [Nullstack Context](/context#----nullstack-context) +- Availability: **client** +- **readwrite** in **client** context + +It gives you all active instances of the application. + +> 💡 Active instances are the ones created and not yet [terminated](/full-stack-lifecycle#terminate) + +As explained in [instance `key`](/instance-self#instance-key), keys play a big role in defining a unique identifier for components. + +> 🔥 Nullstack trusts its developers to know what they are doing and exposes as much internal behavior for the programmer to do as it wishes, use with caution. + +The default key for class components is a join between the class name and the dom depth like `Counter/1.1` and are hard for humans to interact with. + +The first component of your application will have the key `application` by default. + +> 💡 keys define which instance will be used to render the component, you can use it to force a node to reinstantiate. + +Adding an unique `key` to **Counter** makes it easier to access on `instances` list: + +```jsx +import Nullstack from 'nullstack'; +import Counter from './Counter'; +import AnyOtherComponent from './AnyOtherComponent'; + +class Application extends Nullstack { + + render() { + return ( +
+ + +
+ ) + } + +} + +export default Application; +``` + +```jsx +import Nullstack from 'nullstack'; + +class Counter extends Nullstack { + + value = 0; + + increment() { + this.value++; + } + + render() { + return

Count: {this.value}

+ } + +} + +export default Counter; +``` + +You can access any methods and instance variables from **counter** instance on **AnyOtherComponent**: + +```jsx +import Nullstack from 'nullstack'; + +class AnyOtherComponent extends Nullstack { + + render({ instances }) { + return ( + + ) + } + +} + +export default AnyOtherComponent; +``` + +The use of `instances` unlocks unlimited custom behaviors like: + +- A notification icon at the navbar that can be updated from other components at certain actions +- A *toast* component that can be invoked from anywhere in your application +- A *store* system with custom dispatch methods similar to Redux +- Something we haven't even imagined, dream on and post your ideas on GitHub! \ No newline at end of file diff --git a/i18n/en-US/articles/context-page.md b/i18n/en-US/articles/context-page.md index 929826b2..351786e9 100644 --- a/i18n/en-US/articles/context-page.md +++ b/i18n/en-US/articles/context-page.md @@ -133,8 +133,4 @@ class Application extends Nullstack { export default Application; ``` -> 🔥 Assigning to the `status` key during the [single-page application](/full-stack-lifecycle) mode will have no effect. - -## Next step - -⚔ Learn about the [context `project`](/context-project). \ No newline at end of file +> 🔥 Assigning to the `status` key during the [single-page application](/full-stack-lifecycle) mode will have no effect. \ No newline at end of file diff --git a/i18n/en-US/articles/context-project.md b/i18n/en-US/articles/context-project.md index 9f691249..12ac9f2d 100644 --- a/i18n/en-US/articles/context-project.md +++ b/i18n/en-US/articles/context-project.md @@ -13,18 +13,16 @@ It gives you information about the app manifest and some metatags. `project` keys will be used to generate metatags during server-side rendering and must be assigned before [`initiate`](/full-stack-lifecycle) is resolved. -`project` keys will be used to generate the app **manifest** and should be set during the [application startup](/application-startup). +`project` keys will be used to generate the app **manifest**. -The `disallow` key will be used to generate the **robots.txt** and should be set during the [application startup](/application-startup). +The `disallow` key will be used to generate the **robots.txt**. -`project` keys are frozen after the [application startup](/application-startup). +The following keys are available in the object and supported as environment variables as follows: -The following keys are available in the object: - -- **domain**: `string` -- **name**: `string` -- **shortName**: `string` -- **color**: `string` +- **domain**: `string` (`NULLSTACK_PROJECT_DOMAIN`) +- **name**: `string` (`NULLSTACK_PROJECT_NAME`) +- **shortName**: `string` (`NULLSTACK_PROJECT_SHORT_NAME`) +- **color**: `string` (`NULLSTACK_PROJECT_COLOR`) - **backgroundColor**: `string` - **type**: `string` - **display**: `string` @@ -35,12 +33,14 @@ The following keys are available in the object: - **favicon**: `string` (relative or absolute url) - **disallow**: `string array` (relative paths) - **sitemap**: `boolean` or `string` (relative or absolute url) -- **cdn**: `string` (absolute url) -- **protocol**: `string` (http or https) +- **cdn**: `string` (`NULLSTACK_PROJECT_CDN`) +- **protocol**: `string` (`NULLSTACK_PROJECT_PROTOCOL`) Besides `domain`, `name` and `color` all other keys have sensible defaults generated based on the application scope. -If you do not declare the `icons` key, Nullstack will scan any icons with the name following the pattern "icon-[WIDTH]x[HEIGHT].png" in your public folder. +If you do not declare the `icons` key, Nullstack will scan any icons with the name following the pattern "icon-[WIDTH]x[HEIGHT].png" in your **public** folder. + +The `head` meta tag `apple-touch-icon` will be set to your `icon-180x180.png` file. If the `sitemap` key is set to true your **robots.txt** file will point the sitemap to `https://${project.domain}/sitemap.xml`. @@ -49,32 +49,46 @@ The `cdn` key will prefix your asset bundles and will be available in the contex The `protocol` key is "http" in development mode and "https" in production mode by default. ```jsx +// server.js import Nullstack from 'nullstack'; +import Application from './src/Application'; + +const context = Nullstack.start(Application); + +context.start = function() { + const { project } = context; + project.name = 'Nullstack'; + project.shortName = 'Nullstack'; + project.domain = 'nullstack.app'; + project.color = '#d22365'; + project.backgroundColor = '#d22365'; + project.type = 'website'; + project.display = 'standalone'; + project.orientation = 'portrait'; + project.scope = '/'; + project.root = '/'; + project.icons = { + '72': '/icon-72x72.png', + '128': '/icon-128x128.png', + '512': '/icon-512x512.png' + }; + project.favicon = '/favicon.png'; + project.disallow = ['/admin']; + project.sitemap = true; + project.cdn = 'cdn.nullstack.app'; + project.protocol = 'https'; +} -class Application extends Nullstack { +export default context; +``` - static async start({project}) { - project.name = 'Nullstack'; - project.shortName = 'Nullstack'; - project.domain = 'nullstack.app'; - project.color = '#d22365'; - project.backgroundColor = '#d22365'; - project.type = 'website'; - project.display = 'standalone'; - project.orientation = 'portrait'; - project.scope = '/'; - project.root = '/'; - project.icons = { - '72': '/icon-72x72.png', - '128': '/icon-128x128.png', - '512': '/icon-512x512.png' - }; - project.favicon = '/favicon.png'; - project.disallow = ['/admin']; - project.sitemap = true; - project.cdn = 'cdn.nullstack.app'; - project.protocol = 'https'; - } +> More about the `context.start` at [application startup](/application-startup) + +```jsx +// src/Application.njs +import Nullstack from 'nullstack'; + +class Application extends Nullstack { prepare({project, page}) { page.title = project.name; @@ -85,8 +99,4 @@ class Application extends Nullstack { export default Application; ``` -> 💡 You can override the automatically generated **manifest.json** and **robots.txt** by serving your own file from the **public** folder - -## Next step - -⚔ Learn about the [context `settings`](/context-settings). \ No newline at end of file +> 💡 You can override the automatically generated **manifest.json** and **robots.txt** by serving your own file from the **public** folder \ No newline at end of file diff --git a/i18n/en-US/articles/context-secrets.md b/i18n/en-US/articles/context-secrets.md index 8869db0b..3c52fc79 100644 --- a/i18n/en-US/articles/context-secrets.md +++ b/i18n/en-US/articles/context-secrets.md @@ -10,31 +10,32 @@ description: The secrets object is a proxy in the Nullstack Context available in You can use it to configure your application with private information. -`secrets` keys are frozen after the [application startup](/application-startup). +You can assign any keys with any type to the object. -The following keys are available in the object: +You can assign keys to `secrets` dynamically based on current environment using [`context.environment`](/context-environment). -- **development**: `object` -- **production**: `object` -- **[anySetting]**: `any` +```jsx +// server.js +import Nullstack from 'nullstack'; +import Application from './src/Application'; -You can assign keys to `development` or `production` keys in order to have different secrets per [environment](/context-environment). +const context = Nullstack.start(Application); -If you assign a key directly to the `secrets` object it will be available in both environments. +context.start = function() { + const { secrets, environment } = context; + secrets.endpoint = 'https://domain.com/api'; + secrets.privateKey = environment.development ? 'DEV_API_KEY' : 'PROD_API_KEY'; +} -When reading from a key you must read directly from the `secrets` object and Nullstack will return the best-suited value for that [environment](/context-environment). +export default context; +``` ```jsx +// src/Application.njs import Nullstack from 'nullstack'; class Application extends Nullstack { - static async start({secrets}) { - secrets.development.privateKey = 'SANDBOX_API_KEY'; - secrets.production.privateKey = 'PRODUCTION_API_KEY'; - secrets.endpoint = 'https://domain.com/api'; - } - static async fetchFromApi({secrets}) { const response = await fetch(secrets.endpoint, { headers: { @@ -49,10 +50,6 @@ class Application extends Nullstack { export default Application; ``` -Any environment key starting with NULLSTACK_SECRETS_ will be mapped to the secrets in that environment. - -> 🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY will be mapped to `secrets.privateKey` - -## Next step +Any environment variable starting with NULLSTACK_SECRETS_ will be mapped to the `secrets` in that environment. -⚔ Learn about the [instance self](/instance-self). \ No newline at end of file +> 🐱‍💻 NULLSTACK_SECRETS_PRIVATE_KEY will be mapped to `secrets.privateKey` \ No newline at end of file diff --git a/i18n/en-US/articles/context-settings.md b/i18n/en-US/articles/context-settings.md index 959a9f0b..fb45ae00 100644 --- a/i18n/en-US/articles/context-settings.md +++ b/i18n/en-US/articles/context-settings.md @@ -11,31 +11,32 @@ description: The settings object is a proxy in the Nullstack Context available i You can use it to configure your application with public information. -`settings` keys are frozen after the [application startup](/application-startup). +You can assign any keys with any type to the object. -The following keys are available in the object: +You can assign keys to `settings` dynamically based on current environment using [`context.environment`](/context-environment). -- **development**: `object` -- **production**: `object` -- **[anySetting]**: `any` +```jsx +// server.js +import Nullstack from 'nullstack'; +import Application from './src/Application'; -You can assign keys to `development` or `production` keys in order to have different settings per [environment](/context-environment). +const context = Nullstack.start(Application); -If you assign a key directly to the `settings` object it will be available in both environments. +context.start = function() { + const { settings, environment } = context; + settings.endpoint = 'https://domain.com/api'; + settings.publicKey = environment.development ? 'DEV_API_KEY' : 'PROD_API_KEY'; +} -When reading from a key you must read directly from the `settings` object and Nullstack will return the best-suited value for that [environment](/context-environment). +export default context; +``` ```jsx +// src/Application.njs import Nullstack from 'nullstack'; class Application extends Nullstack { - static async start({settings}) { - settings.development.publicKey = 'SANDBOX_API_KEY'; - settings.production.publicKey = 'PRODUCTION_API_KEY'; - settings.endpoint = 'https://domain.com/api'; - } - async hydrate({settings}) { const response = await fetch(settings.endpoint, { headers: { @@ -50,10 +51,6 @@ class Application extends Nullstack { export default Application; ``` -Any environment key starting with NULLSTACK_SETTINGS_ will be mapped to the settings in that environment. - -> 🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY will be mapped to `settings.publicKey` - -## Next step +Any environment variable starting with NULLSTACK_SETTINGS_ will be mapped to the `settings` in that environment. -⚔ Learn about the [context `secrets`](/context-secrets). \ No newline at end of file +> 🐱‍💻 NULLSTACK_SETTINGS_PUBLIC_KEY will be mapped to `settings.publicKey` \ No newline at end of file diff --git a/i18n/en-US/articles/context.md b/i18n/en-US/articles/context.md index 71313c22..dd39286f 100644 --- a/i18n/en-US/articles/context.md +++ b/i18n/en-US/articles/context.md @@ -34,10 +34,9 @@ These are the information that the framework makes available to you by default. - [`response`](/server-request-and-response#request-and-response) - [`secrets`](/context-secrets) -### The available instance client keys are: +### The key available only in client: -- [`self`](/instance-self) -- [`children`](/renderable-components#components-with-children) +- [`instances`](/context-instances) ## 2 - Application Context @@ -45,7 +44,7 @@ When you set a key to the context it will be available for destructuring at any Updating a key in the context causes the application to re-render automatically. -You can think of this as a single concept to replace **stores**, **contexts**, **services**, and **reducers** at the same time using the dependency injection pattern with vanilla javascript objects instead. +You can think of this as a single concept to replace **stores**, **contexts**, **services**, and **reducers** at the same time using the dependency injection pattern with vanilla JavaScript objects instead. ```jsx import Nullstack from 'nullstack'; @@ -82,7 +81,7 @@ import Counter from './Counter'; class Application extends Nullstack { - static async start(context) { + prepare(context) { context.totalCount = 0; } @@ -101,7 +100,11 @@ export default Application; ## 3 - Component Context -This one contains the attributes you declare in your tag, including [`data`](/context-data). +This one contains the attributes you declare in your tag, and including: + +- [`data`](/context-data) +- [`self`](/instance-self) +- [`children`](/jsx-elements#components-with-children) If the attribute is declared in a component tag every function of that component will have access to that attribute in its context. @@ -180,8 +183,4 @@ class Counter extends Nullstack { } export default Counter; -``` - -## Next step - -⚔ Learn about [routes and params](/routes-and-params). \ No newline at end of file +``` \ No newline at end of file diff --git a/i18n/en-US/articles/frequently-asked-questions.md b/i18n/en-US/articles/frequently-asked-questions.md new file mode 100644 index 00000000..a1627f6b --- /dev/null +++ b/i18n/en-US/articles/frequently-asked-questions.md @@ -0,0 +1,63 @@ +--- +title: Frequently Asked Questions +description: Nullstack is an isomorphic JavaScript framework that allows developers to build Full Stack applications while staying focused on the product features, and solving the user problems, rather than spending a significant amount of their time worrying about layers of abstraction and choosing which tools make them look fancy +--- + +## What is feature-driven? +It means that every component is a full feature in itself, but it is up to you to decide how to break features down. As an example, you could have a "BlogPost" component or you could have a Blog a Post a Comment, and a Like component and they are nested into each other, heck you could even have an entire e-commerce application be a top-level component imported in another application, that's the beauty of full stack components. + +In the case of a Like button for instance, you would have the server functions to load the number of likes that item has, a render function to show your likes, and an event that triggers a server function to save your like, all in a single file if you want, the main reasoning for this architecture is that the project manager's tickets, the UX and the code look pretty much the same. + +*- But my bootcamp teacher said I need at least 3 layers of abstraction to be a good developer, can I do that in Nullstack?* + +Yes you can, Nullstack is a big foot-gun you can shoot your own foot in your favorite style, just ask for the permission of an adult first. + +## Is it a react framework? +Nope, but it uses JSX. Nullstack does not use hooks, instead, it aims to keep JavaScript's natural flow, but makes it reactive. Fun fact tho, Nullstack actually started as a react framework that just aimed to add server functions to the components, but eventually, I found that sticking to that model was limiting our creativity. + +## Why did you build another framework? +That wasn't the original intention, We were actually trying to build a coffee shop, but We get distracted very easily... you can learn more about the history behind Nullstack in [Anny's TDC talk](https://www.youtube.com/watch?v=77qeq6cSHG8). + +Initially, We just wanted to put the server code alongside the client code, because the projects We were working on had very similar patterns, and one of those patterns was that the clients would completely change their minds all the time, and your regular clean code kinda thing was not keeping up with the changes. + +I often noticed myself trying to fit into the format of the framework and changing features, or even avoiding creating new API endpoints because i didn't wanna make things to coupled or complicated. In Nullstack i just need to create a new function in the same class that just returns whatever data i need just for that case, which makes me a lot more productive and makes me think of what i'm building a lot more often than how i am building it. + +## Does it use a virtual dom or a compiler or signals? +The answer is yes. Nullstack has what I like to call a "Virtual Pipeline" it optimizes things differently in different scenarios for different environments. However that is just an implementation detail, the main thing is that it **just works** and We may change anything internal at any time. The only condition We have is that anything that works in vanilla JS should work in Nullstack, so We won't adopt any cool new trends if it limits the developer experience, or if the developer now needs to be aware of new edge cases instead of getting stuff done. + +## Does it uses Classes or Functions? +It uses whatever JavaScript code you can come up with. By default it follows the same paradigm as vanilla: functions are pure, and classes hold state. I know I will lose a lot of devs after the previous sentence, but keep in mind when people say "classes are bad" they actually mean "classes are bad on the current framework I'm using" . In Nullstack it just feels very natural, give it a try. + +## Is it blazingly fast? +Yes. But it is optimized for what I consider the "right type of fast", it's fast for the users. It uses a mix of architectures to optimize for different scenarios, but all of them aim to have the users have very responsive experiences, even when they are offline. + +You can always benchmark things and be excited about microseconds, but that all ends when your user 3g is not feeling like reaching your server that day. + +That being said, We love spending time micro benchmarking things and it's actually pretty fast, if you sneak into our commit history you will notice We went for "what We need to create products" first then We went "optimization happy", as you should if you plan to code professionally and not just watching clickbait. + +![Nullstack's documentation lighthouse score](/lighthouse.webp) + +## What can i build with it? Does it scale? +You can build anything you can build with regular JavaScript. We've built so far plenty of PWAs, blockchain applications across multiple blockchains (dApps), mobile games, capacitor applications, electron applications, chrome extensions, and even things to visualize [brain to computer interface](https://ae.studio/brain-computer-interface) data that require a lot of performance. Currently, We have a SaaS with hundreds of thousands of hits a day, and it is holding just fine on a "regular JavaScript-priced" server. + +## How can i use a new framework? it won't have an ecosystem. +Remember when I mentioned We keep everything vanilla just working? that makes most JavaScript packages for browser and server compatible with Nullstack out of the box, that's a pretty huge ecosystem in my opinion. But also if you are feeling like a mad scientist, you could always just install your favorite framework on top of a Nullstack's application by rendering to an element controlled by it. + +## Does it have any kind of telemetry? +No, We do not collect any data. Nullstack was not built as a framework first, it was extracted from real applications We worked on over the years, so the features it has are based on what We needed as opposite of what the data would point would cause better thumbnails. + +*- But how will you guys know what features We want then?* + +You can always tell us on discord or [create an issue on GitHub](https://github.com/nullstack/nullstack/issues), We will be happy to talk about it! + +## Does Nullstack have any social media? +Of the 6 main contributors of Nullstack 6 of them are autistic, including the person writing this wall of text... so you mostly lost us at the "social" part. We did try tho, and We created a [YouTube Channel](https://www.youtube.com/nullstack), a [Twitter](https://twitter.com/nullstackapp), and an [Instagram](https://www.instagram.com/nullstackapp/), but 4 of us also have ADHD so We ended up procrastinating and not posting on it, oopsie. We are pretty active on [Discord](https://discord.gg/eDZfKz264v) though, that's the place We are forced to log in anyway to coordinate our raids. + +## What is Nulla-Chan? +Nulla-Chan is the avatar of Nullstack, it belongs to a category of avatars called a "Waifu". If you don't know what a waifu is, that probably means that you have your life on the right track. Fun fact, the waifu character was created by the author's IRL waifu. + +## What was the hardest part creating a framework? +Definitively it was deciding if We should spell it "full stack", "fullstack", or "full-stack". Seriously please tell us on discord which one to pick. + +## How can i get started? +Just go to your favorite terminal and type "npx create-nullstack-app app-name" and use the templates available through the CLI. \ No newline at end of file diff --git a/i18n/en-US/articles/full-stack-lifecycle.md b/i18n/en-US/articles/full-stack-lifecycle.md index b539a0fa..66dd2858 100644 --- a/i18n/en-US/articles/full-stack-lifecycle.md +++ b/i18n/en-US/articles/full-stack-lifecycle.md @@ -1,5 +1,5 @@ --- -title: Full-Stack Lifecycle +title: Full Stack Lifecycle description: Lifecycle methods are special named functions that you can declare in the class. --- @@ -47,6 +47,8 @@ Nullstack will wait till the promise is resolved and then finally generate the H If the user is navigating from another route this method will run in the client. +After this method promise is fulfilled `this.initiated` will be set to true + ```jsx import Nullstack from 'nullstack'; @@ -60,7 +62,12 @@ class Component extends Nullstack { }); } - // ... + render() { + if(!this.initiated) return false + return ( +

{this.task.description}

+ ) + } } @@ -69,6 +76,32 @@ export default Component; > ✨ Learn more about [server functions](/server-functions). +## Launch + +Runs before pre-rendering and at each awakening. + +You can update the component with things that doesn't require data fetching operations. + +> ✨ Use this lifecycle to setup Meta tags. + +```jsx +import Nullstack from 'nullstack'; + +class Component extends Nullstack { + + // ... + + launch({ page }) { + page.title = 'Very good title that considers SEO' + } + + // ... + +} + +export default Component; +``` + ## Hydrate This method is async and will only run in the client. @@ -77,6 +110,8 @@ This method will always run no matter which environment started the component. This is a good place to trigger dependencies that manipulate the dom or can only run on the client-side. +After this method promise is fulfilled `this.hydrated` will be set to true + ```jsx import Nullstack from 'nullstack'; @@ -90,7 +125,12 @@ class Component extends Nullstack { }, 1000); } - // ... + render() { + if(!this.hydrated) return false + return ( +

timer id: {this.timer}

+ ) + } } @@ -143,6 +183,8 @@ This is the place to clean up whatever you set up in the `hydrate` method. The instance will be garbage collected after the `Promise` is resolved. +After this method promise is fulfilled `this.terminated` will be set to true which is useful in the case of [persistent components](/persistent-components) + ```jsx import Nullstack from 'nullstack'; @@ -154,13 +196,15 @@ class Component extends Nullstack { clearInterval(this.timer); } + executeBackgroundTask() { + if(!this.terminated) { + // ... + } + } + // ... } export default Component; -``` - -## Next steps - -⚔ Learn about [server functions](/server-functions). \ No newline at end of file +``` \ No newline at end of file diff --git a/i18n/en-US/articles/getting-started.md b/i18n/en-US/articles/getting-started.md index ab8ba026..00102d3b 100644 --- a/i18n/en-US/articles/getting-started.md +++ b/i18n/en-US/articles/getting-started.md @@ -1,22 +1,23 @@ --- title: Getting Started -description: Create full-stack javascript applications within seconds +description: Create full stack JavaScript applications within seconds +action: ⚔ Learn [how to create a nullstack project](/getting-started). --- > 📌 You can watch a video tutorial on our [Youtube Channel](https://www.youtube.com/watch?v=l23z00GEar8&list=PL5ylYELQy1hyFbguVaShp3XujjdVXLpId). -Create full-stack javascript applications within seconds using `npx` to generate your project files from the latest template. +Create full stack JavaScript applications within seconds using `npx` to generate your project files from the latest template. -> 🔥 The minimum required [node.js](https://nodejs.org) version for development mode is *12.12.0*. - -> ⚠ If the directory you are in contains spaces, you use Windows and `npx` gives errors, read about [the known npx bug](#the-known-npx-bug). +> 🔥 The minimum required [node.js](https://nodejs.org) version for development mode is *12.20.0*. Replace `project-name` with your project name and run the command below to start a project: ```sh -npx create-nullstack-app project-name +npx create-nullstack-app@latest project-name ``` +> 💡 You can use a CLI to select the blank javascript or typescript template or select the template with tailwind css. + Change directory to the generated folder: ```sh @@ -26,42 +27,52 @@ cd project-name Install the dependencies: ```sh -npm install +npm install # or yarn ``` Start the application in development mode: ```sh -npm start +npm start # or yarn start ``` ## Understanding the generated files The following folders and files will be generated: -### index.js +### server.js + +This is the server entry and generator point. + +It is a convenient place to set up global things like [database](/how-to-use-mongodb-with-nullstack) and manipulate server `context`, details in [application startup](/application-startup). -This is the [Webpack](https://webpack.js.org) entry point. +### client.js -Usually, you don't have to touch this file, but it is a convenient place to import global dependencies like CSS frameworks. +This is the client entry and generator point. + +It is a convenient place to import global dependencies like CSS frameworks and manipulate client `context`. ### src/ This folder will contain the actual source code of your application. -### src/Application.njs +### src/Application.jsx This is your application main file. ->✨ Learn more about the [njs file extension](/njs-file-extension "Nullstack Javascript"). +>✨ Learn more about the [jsx elements](/jsx-elements "Nullstack JavaScript"). -The `start` function will be automatically called once when you run `npm start`, use it to populate your server [context](/context) with things like [database](/how-to-use-mongodb-with-nullstack), [settings](/context-settings), and [secrets](/context-secrets). +When you run `npm start` it is consumed in **server**/**client** JS files by their `Nullstack.start` function, which starts and returns both [`context`](/context), that you can use to set up things like [database](/how-to-use-mongodb-with-nullstack) using [settings](/context-settings) and [secrets](/context-secrets). >✨ Learn more about the [application startup](/application-startup). -### src/Application.scss +#### TypeScript + +You can use Nullstack with TypeScript, just rename `njs` to `nts` or `jsx` to `tsx`. -This is an empty file just to demonstrate that you can use [SCSS with Nullstack](/styles). +### src/Application.css + +This is an empty file just to demonstrate that you can use [CSS with Nullstack](/styles). It is a good practice to import a style file in a component with the same name. @@ -89,32 +100,4 @@ This is the compiled result of your application in production mode. > 🔥 Do not touch this folder ->✨ Learn more about [how to deploy a Nullstack application](/how-to-deploy-a-nullstack-application). - -## The known npx bug - -Warned on `npx` issues like [#100](https://github.com/zkat/npx/issues/100), [#110](https://github.com/zkat/npx/issues/110) and [#143](https://github.com/zkat/npx/issues/146), it has an error when trying to resolve the path to his cache folder when contains spaces. - -If this happens to you, our recommendations are: - -- Using downloaded as you normally would with `npm`: - ```sh - npm i -g create-nullstack-app - create-nullstack-app project-name - ``` - -- or, change the cache folder directory, as stated [here](https://github.com/zkat/npx/issues/146#issuecomment-384016791) and [here](https://github.com/zkat/npx/issues/146#issuecomment-384019497): - - - If you want to keep the use of space, replace `FirstName` with the one used on your path and run: - ```sh - npm config set cache "C:\Users\FirstName~1\AppData\Roaming\npm-cache" --global - ``` - - - or, using another path without spaces: - ```sh - npm config set cache C:\tmp\nodejs\npm-cache --global - ``` - -## Next step - -⚔ Create your first [renderable component](/renderable-components). \ No newline at end of file +>✨ Learn more about [how to deploy a Nullstack application](/how-to-deploy-a-nullstack-application). \ No newline at end of file diff --git a/i18n/en-US/articles/how-to-customize-webpack.md b/i18n/en-US/articles/how-to-customize-webpack.md new file mode 100644 index 00000000..0a953a4f --- /dev/null +++ b/i18n/en-US/articles/how-to-customize-webpack.md @@ -0,0 +1,58 @@ +--- +title: How to customize Webpack +description: You can create your own custom webpack config to extend Nullstacks default configs +--- + +You can create your own custom `webpack.config.js` at the projects root folder to extend Nullstacks default configs + +Nullstack exposes the file `nullstack/webpack.config.js` which exports a server and client function, each being the config for the respective environment + +You can import nullstack webpack config with the following code + +```jsx +const [server, client] = require('nullstack/webpack.config'); + +module.exports = [server, client] +``` + +You can customize a single environment by wrapping the targeted function + +```jsx +const [server, client] = require('nullstack/webpack.config'); + +const glob = require('glob'); +const PurgecssPlugin = require('purgecss-webpack-plugin'); + +function customClient(...args) { + const config = client(...args); + if (config.mode === 'production') { + config.plugins.push(new PurgecssPlugin({ + paths: glob.sync(`src/**/*`, { nodir: true }), + content: ['./**/*.njs'], + safelist: ['script', 'body', 'html', 'style'], + defaultExtractor: content => content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [], + })); + } + + return config; +} + +module.exports = [server, customClient] +``` + +You can also extend both environments at once by creating a wrapper around both environments + +```jsx +const [server, client] = require('nullstack/webpack.config'); +const CadencePlugin = require('cadence-webpack-plugin'); + +function applyCadencePlugin(environments) { + return environments.map((environment) => (...args) => { + const config = environment(...args); + config.plugins.push(new CadencePlugin()) + return config; + }) +} + +module.exports = applyCadencePlugin([server, client]) +``` \ No newline at end of file diff --git a/i18n/en-US/articles/how-to-deploy-a-nullstack-application.md b/i18n/en-US/articles/how-to-deploy-a-nullstack-application.md index 22e01413..70212281 100644 --- a/i18n/en-US/articles/how-to-deploy-a-nullstack-application.md +++ b/i18n/en-US/articles/how-to-deploy-a-nullstack-application.md @@ -33,8 +33,8 @@ node .production/server.js After you [generate a static site](/static-site-generation), all you have to do is move the output folder to any host machine capable of serving HTML. -## Next step +## Examples -> 🎉 **Congratulations**. You are done with the advanced concepts! - -⚔ Learn [how to use MongoDB with Nullstack](/how-to-use-mongodb-with-nullstack). \ No newline at end of file +- [How to deploy to Vercel](/examples/how-to-deploy-to-vercel) +- [How to deploy to Github Pages](/examples/how-to-deploy-to-github-pages) +- [How to deploy to Heroku](/examples/how-to-deploy-to-heroku) \ No newline at end of file diff --git a/i18n/en-US/articles/instance-self.md b/i18n/en-US/articles/instance-self.md deleted file mode 100644 index bab34b0d..00000000 --- a/i18n/en-US/articles/instance-self.md +++ /dev/null @@ -1,265 +0,0 @@ ---- -title: Instance Self -description: The self object is a proxy in the Nullstack Context available in client and gives you information about the instance lifecycle ---- - -- Type: `object` -- Origin: [Nullstack Context](/context#----nullstack-context) -- Availability: **client** -- **readonly** in **client** context - -It gives you information about the instance lifecycle and it's unique [`key`](#instance-key). - -Each instance receives its own `self` object. - -The following keys are available in the object: - -- [`key`](#instance-key): `string` - -When a lifecycle method is resolved, even if not declared, an equivalent key is set to `true` in `self`. - -If the component was server-side rendered the `prerendered` key will remain `true` until it is terminated. - -The `element` key points to the DOM selector and is only guaranteed to exist when `hydrate` is being called since `prepare` and `initiate` could run in the server. - -> 💡 Do not use `element` to guess the environment, instead use the [`environment`](/context-environment) for that. - -Observing `self` is a nice way to avoid giving placeholder information to the end-user. - -```jsx -import Nullstack from 'nullstack'; - -class Page extends Nullstack { - - // ... - - async initiate() { - this.price = await this.getPrice(); - } - - async hydrate({self}) { - self.element.querySelector('input').focus(); - } - - render({self}) { - if(!self.prerendered && !self.initiated) return false; - return ( -
- - -
- ) - } - -} - -export default Page; -``` - -> 💡 Components that get optimized into [functional components](/renderable-components) have no access to `self`. - -## Instance Key - -- Type: `string` -- Origin: [Component Context](/context#----component-context) -- Availability: **client** -- **readonly** in **client** context or after defined it's value as attribute - -It allows you to persist the instance when it moves in the dom. - -You can declare one `key` per instance. - -> 💡 If you do not declare a `key` nullstack will generate one based on dom depth. - -> 🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys - -Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings. - -### Preserving state - -Keys are useful to preserve state in [stateful components](/stateful-components) when you move them in the dom. - -This is especially useful for dynamically sized lists that invoke components. - -```jsx -import Nullstack from 'nullstack'; -import Item from './Item'; - -class List extends Nullstack { - - // ... - - async initiate() { - this.items = await this.getItems(); - } - - render({self}) { - const componentKey = self.key; - return ( -
    - {this.items.map((item) => ( - - ))} -
- ) - } - -} - -export default Page; -``` - -### Shared Instances - -You can also use keys to share the instance between two elements. - -Only the first encounter of the `key` will run its [lifecycle](/full-stack-lifecycle). - -```jsx -import Nullstack from 'nullstack'; - -class Counter extends Nullstack { - - count = 0; - - render({amount}) { - return ( -
- -
- ) - } - -} - -export default Counter; -``` - -```jsx -import Nullstack from 'nullstack'; -import Counter from './Counter'; - -class Application extends Nullstack { - - render() { - return ( -
- - - -
- ) - } - -} - -export default Application; -``` - -## Instance Key - -- Type: `string` -- Origin: [Component Context](/context#----component-context) -- Availability: **client** -- **readonly** in **client** context or after defined it's value as attribute - -It allows you to persist the instance when it moves in the dom. - -You can declare one key per instance. - -> 💡 If you do not declare a key nullstack will generate one based on dom depth. - -> 🔥 Keys cannot start with "_." to avoid conflicts with Nullstack generated keys - -Keys must be globally unique since the component could move anywhere around the dom and not only between its siblings. - -### Preserving state - -Keys are useful to preserve state in [stateful components](/stateful-components) when you move them in the dom. - -This is especially useful for dynamically sized lists that invoke components. - -```jsx -import Nullstack from 'nullstack'; -import Item from './Item'; - -class List extends Nullstack { - - // ... - - async initiate() { - this.items = await this.getItems(); - } - - render({self}) { - const componentKey = self.key; - return ( -
    - {this.items.map((item) => ( - - ))} -
- ) - } - -} - -export default Page; -``` - -### Shared Instances - -You can also use keys to share the instance between two elements. - -Only the first encounter of the key will run its [lifecycle](/full-stack-lifecycle) - -```jsx -import Nullstack from 'nullstack'; - -class Counter extends Nullstack { - - count = 0; - - render({amount}) { - return ( -
- -
- ) - } - -} - -export default Counter; -``` - -```jsx -import Nullstack from 'nullstack'; -import Counter from './Counter'; - -class Application extends Nullstack { - - render() { - return ( -
- - - -
- ) - } - -} - -export default Application; -``` - -## Next step - -⚔ Learn about the [server request and response](/server-request-and-response). \ No newline at end of file diff --git a/i18n/en-US/articles/renderable-components.md b/i18n/en-US/articles/jsx-elements.md similarity index 61% rename from i18n/en-US/articles/renderable-components.md rename to i18n/en-US/articles/jsx-elements.md index a4d3569c..623278b4 100644 --- a/i18n/en-US/articles/renderable-components.md +++ b/i18n/en-US/articles/jsx-elements.md @@ -1,68 +1,8 @@ --- -title: Renderable Components -description: Renderable components are very similar to web components they give you the ability to create new HTML tags that shortcut a group of other HTML tags +title: JSX elements +description: Nullstack JSX deviates a little from the spec. --- -The simplest component you can make is a renderable component. - -Renderable components are very similar to web components, they give you the ability to create new HTML tags that shortcut a group of other HTML tags. - -Create a file in your src folder with the name of your component and the [njs extension](/njs-file-extension). - -In this example it is going to be called HelloWorld.njs. - -All you have to do is to import Nullstack or any of its subclasses and extend your class from it, define an instance method called render that returns any JSX, and export the component. - -> ✨ Install the official [Nullstack VSCode Extension](https://marketplace.visualstudio.com/items?itemName=ChristianMortaro.vscode-nullstack) to generate classes with a snippet. - -```jsx -import Nullstack from 'nullstack'; - -class HelloWorld extends Nullstack { - - render() { - return ( -
Hello World
- ) - } - -} - -export default HelloWorld; -``` - -The code above is just declaring the component, you still have to use it. - -Importing the component in your application gives you the ability to use a new tag in your render. - -This tag will be replaced with whatever you returned in your component render. - -```jsx -import Nullstack from 'nullstack'; - -import './Application.scss'; - -import HelloWorld from './HelloWorld'; - -class Application extends Nullstack { - - // ... - - render({page}) { - return ( -
-

{page.title}

- Read the documentation - -
- ) - } - -} - -export default Application; -``` - ## Using HTML attributes Nullstack JSX deviates a little from the spec. @@ -97,49 +37,6 @@ This is also useful for conditional rendering. If all you want to do is to generate an invisible component you can skip defining the render method at all. -## Inner components - -Instead of creating a new component just to organize code-splitting, you can create an inner component. - -Inner components are any method that the name starts with `render` followed by an uppercase character. - -Inner components share the same instance and scope as the main component, therefore, are very convenient to avoid problems like props drilling. - -To invoke the inner component use a JSX tag with the method name without the `render` prefix. - -```jsx -import Nullstack from 'nullstack'; - -class Post extends Nullstack { - - renderArticle() { - return ( -
Content
- ) - } - - renderAside() { - return ( - - ) - } - - render() { - return ( -
-
-
- ) - } - -} - -export default HelloWorld; -``` - -> 💡 Nullstack will inject a constant reference to the function at transpile time in order to completely skip the runtime lookup process! - ## Boolean attributes Attributes can be assigned as a boolean. @@ -172,6 +69,30 @@ If you need to decide the tag name at runtime, you can use the element tag and s When the tag attribute is omitted, Nullstack will default to a `div`. +## Fragments + +Fragments are elements that renders it's contents in the parent component. + +```jsx +export default function Fragmented() { + return ( + <> + <> + + +

Paragraph!

+ + ) +} +``` + +Wherever it is used, the above functional component will be rendered as follows: + +```html + +

Paragraph!

+``` + ## SVG Elements SVG can be used as if it were any regular HTML tag. @@ -222,6 +143,8 @@ export default Header; You can map over lists without declaring a `key`. +> ✨ A key in Nullstack is an ID for a specific component instance. Learn more about the [instance key](/instance-self#instance-key). + Lists that may change length must be wrapped in a parent element just for them. ```jsx @@ -271,8 +194,6 @@ class List extends Nullstack { export default List; ``` -> ✨ Sometimes you will notice keys in the map. Learn more about the [instance key](/instance-self#instance-key). - ## Inner HTML You can set the inner HTML of an element with the `html` attribute. @@ -304,11 +225,39 @@ export default Post; > 🔥 Be careful! When using user-generated HTML you are in risk of script injection -## The head tag +## Body tag -Renderable components can render inside the `head` tag an unlimited number of times at any depth of the application. +Renderable components can render a `body` tag an unlimited number of times at any depth of the application. + +The `body` attributes of the body tag that are rendered will be merged into the real body tag in the DOM + +```jsx +import Nullstack from 'nullstack'; + +class Application extends Nullstack { + + // ... + + render() { + return ( + + {this.modalOpen && + +