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! ╰(*°▽°*)╯