Pular para o conteúdo principal

Criando uma aplicação

Nessa página, vamos construir um site para a nossa livraria que consome o conteúdo que acabamos de criar no Starlight.

O Starlight te dá liberdade de construir aplicações com as linguagens e ferramentas que você preferir. Nesse exemplo, vamos criar nossa aplicação utilizando o Next.js, um framework para aplicações web simples e flexível, e o SDK do Starlight para requisitar o conteúdo que criamos.

Você pode visualizar o código completo do que criaremos nessa página acessando esse repositório do GitHub. O código do repositório foi escrito em TypeScript, mas você verá exemplos em JavaScript e TypeScript nessa página.

Com pressa para terminar?

Se preferir, você pode simplesmente clonar o repositório acima, seguir as instruções do arquivo README.md para configurar a área de trabalho que a aplicação usa para requisitar dados, e simplesmente continuar para a página sobre deploy desse guia. Porém, recomendamos a leitura dessa página caso queira aprender como utilizar o SDK do Starlight para fazer requisições às suas APIs. A gente promete que o processo é super simples.

Criando um projeto com o Next.js

Para começar, abra seu terminal favorito, entre na pasta onde você quer criar seu projeto e rode o seguinte comando:

Terminal
npx create-next-app@latest

Esse comando rodará o create-next-app, a aplicação CLI oficial do Next.js para criar projetos. Você será apresentado com algumas perguntas como o nome do projeto e algumas escolhas de configuração:

Retorno do create-next-app
$ cd Projects
$ npx create-next-app@latest

Need to install the following packages:
create-next-app@latest
Ok to proceed? (y)

✔ What is your project named? … quick-start-bookstore
✔ Would you like to use TypeScript with this project? … Yes
✔ Would you like to use ESLint with this project? … Yes
✔ Would you like to use Tailwind CSS with this project? … Yes
✔ Would you like to use `src/` directory with this project? … Yes
✔ Use App Router (recommended)? … No
✔ Would you like to customize the default import alias? … No

Creating a new Next.js app in /Users/camila/Projects/quick-start-bookstore.

Configure seu projeto da maneira que preferir, mas recomendamos que você responda não para a pergunta Use App Router?, já que não utilizamos o App Router no nosso projeto de exemplo. O App Router ainda está em fase de testes, e por isso decidimos não utilizá-lo nos exemplos desse guia. Além disso, escolhemos instalar o Tailwind CSS para adicionar alguns estilos simples nos exemplos abaixo, mas isso não é obrigatório.

Com o projeto criado, precisamos apenas configurar o Next.js para que ele aceite mostrar imagens providas pelo Starlight. Para isso, altere o arquivo next.config.js na raíz do seu projeto para ter esse conteúdo:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'media.starlightcms.io',
},
],
},
}

module.exports = nextConfig

Finalmente, para rodar o servidor de desenvolvimento, entre na pasta da sua aplicação e utilize o seguinte comando:

npm run dev

Configurando o SDK do Starlight

Com o conteúdo salvo no Starlight, temos duas opções para requisitá-lo: usando as APIs do Starlight ou um SDK oficial. Os SDKs do Starlight simplificam o processo de requisição de conteúdo às suas APIs, e nós vamos utilizar o SDK para Next.js nesse exemplo. Para isso, precisamos instalá-lo:

# Não esqueça de reiniciar o servidor (npm run dev) depois da instalação.
npm install @starlightcms/next-sdk

Após a instalação, precisamos configurar qual área de trabalho deve ser utilizada ao requisitar dados, informando ao SDK o ID dessa área de trabalho. Você pode visualizar (e copiar) o ID de uma área de trabalho ao entrar nela pela interface do Starlight. O ID fica visível abaixo do nome da área de trabalho 1, no menu de navegação à esquerda.

O ID da área de trabalho sempre está disponível no menu de navegação.

Com o ID em mãos, precisamos utilizar o método configure do SDK do Starlight no arquivo que inicializa nossa aplicação. No Next.js, esse arquivo se chama _app.jsx (ou _app.tsx em projetos TypeScript). Crie esse arquivo dentro da pasta pages do seu projeto com o seguinte conteúdo:

pages/_app.jsx
import Starlight from '@starlightcms/next-sdk'
// Remova essa linha se você escolheu não utilizar o Tailwind CSS.
import '@/styles/globals.css'

Starlight.configure({
// Substitua o ID abaixo pelo ID da sua área de trabalho.
workspace: '1234567890',
})

export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
"Tipando" conteúdo no TypeScript

Caso esteja utilizando TypeScript, você pode "tipar" o conteúdo retornado pelo SDK do Starlight. Para isso, crie um arquivo chamado starlight.d.ts dentro da pasta src da sua aplicação com o seguinte conteúdo:

{' '}

src/starlight.d.ts
import '@starlightcms/next-sdk'
import {
MediaField,
VisualField,
StringField,
BooleanField,
} from '@starlightcms/next-sdk'

export type Book = {
title: StringField
slug: StringField
cover_picture: MediaField
isbn: StringField
excerpt: VisualField
is_available: BooleanField
}

declare module '@starlightcms/next-sdk' {
export interface DefaultModelDefinition {
// Use o slug do modelo que você criou caso não tenha usado o slug "books".
books: Book
}
}

Agora, quando você precisar "tipar" o conteúdo de um livro em qualquer lugar da sua aplicação, você pode importar o tipo Book desse arquivo.

E pronto! Agora você pode utilizar o SDK do Starlight no seu projeto.

Escrevendo as rotas da aplicação

Vamos criar duas páginas na nossa aplicação para mostrar o conteúdo que criamos no Starlight:

  • A página inicial (/), que mostra a lista de livros na nossa livraria; e
  • A página de um livro (/livro/slug-de-um-livro), que mostra as informações de um livro específico.

Para isso, precisamos criar dois arquivos que representam essas páginas no nosso projeto:

src/pages/index.js
src/pages/livro/[slug].js

No Next.js, as rotas da nossa aplicação são definidas criando arquivos com a nomeclatura que usamos acima dentro da pasta pages. Se quiser aprender mais sobre como esses arquivos funcionam, dê uma olhada na documentação do roteador do Next.js.

Listagem de livros na página inicial

No Next.js, uma página é um arquivo que exporta um componente React que renderiza conteúdo. Opcionalmente, páginas também podem exportar uma função que requisita dados de APIs externas e os repassa para esse componente.

Sendo assim, vamos começar criando essa função, onde vamos usar o SDK do Starlight para requisitar nossos livros e repassarmos essa lista para o componente que criaremos no próximo passo:

src/pages/index.js
import Starlight, { Image } from '@starlightcms/next-sdk'
import Link from 'next/link'

// Essa função rodará sempre que acessarmos a rota "/", que é a página inicial do nosso site.
export const getServerSideProps = async () => {
// Podemos requisitar conteúdo de um modelo pelo SDK utilizando apenas seu slug.
// Aqui, note que acessamos uma propriedade chamada "books", que é o slug do nosso modelo.
// Se você utilizou outro slug no seu modelo, coloque-o no lugar de "books" na linha abaixo.
const response = await Starlight.books.entries.list()

// O objeto "props" abaixo será repassado pelo Next.js para o
// componente React que vamos criar na próxima etapa.
return {
props: {
// "response" é a resposta completa do Starlight, incluindo metadados.
// Nós só precisamos da lista de livros, que está na propriedade "data".
books: response.data,
}
}
}

Agora, só precisamos adicionar o componente React que vai renderizar nossa página no mesmo arquivo:

Dica

Esse exemplo contém o código completo do arquivo. Ganhe tempo copiando e colando esse conteúdo no seu arquivo local.

src/pages/index.js
import Starlight, { Image } from '@starlightcms/next-sdk'
import Link from 'next/link'

const Home = ({ books }) => (
// Usamos classes do Tailwind CSS para deixar o resultado final mais bonito.
// Se você não escolheu usar o Tailwind CSS, essas classes não terão nenhum efeito.
<main className="container mx-auto p-5 grid grid-cols-1 gap-5 sm:grid-cols-3">
{books.map((book) => (
<Link
key={book.id}
href={`/livro/${book.slug}`}
className="w-full max-w-lg p-5 mx-auto bg-white rounded-lg shadow-md"
>
<article className="h-full flex flex-col items-center justify-center">
{/* Capa do livro */}
<figure className="w-32 mb-4">
{/* O componente Image renderiza uma imagem com todos os metadados (height, width e alt)
automaticamente preenchidos utilizando dados retornados pela API do Starlight. */}
<Image media={book.data.cover_picture} className="rounded"/>
</figure>
{/* Título do livro */}
<h2 className="text-xl font-bold mb-1">{book.title}</h2>
{/* Disponibilidade */}
<p className="text-gray-600 text-center">
{book.data.is_available ? 'Disponível para compra.' : 'Indisponível.'}
</p>
</article>
</Link>
))}
</main>
)

// Essa função rodará sempre que acessarmos a rota "/", que é a página inicial do nosso site.
export const getServerSideProps = async () => {
// Podemos requisitar conteúdo de um modelo pelo SDK utilizando apenas seu slug.
// Aqui, note que acessamos uma propriedade chamada "books", que é o slug do nosso modelo.
// Se você utilizou outro slug no seu modelo, coloque-o no lugar de "books" na linha abaixo.
const response = await Starlight.books.entries.list()

// O objeto "props" abaixo será repassado pelo Next.js para o
// componente React que vamos criar na próxima etapa.
return {
props: {
// "response" é a resposta completa do Starlight, incluindo metadados.
// Nós só precisamos da lista de livros, que está na propriedade "data".
books: response.data,
}
}
}

export default Home
Export default

Note que estamos exportando o componente na última linha utilizando export default Home. É assim que o Next.js sabe o que renderizar quando acessamos essa rota.

E pronto! Você pode acessar a listagem de livros na sua aplicação acessando a página inicial pelo endereço http://localhost:3000.

Página de detalhes de um livro

Requisitar os dados de um livro específico usando o Starlight não é muito diferente da requisição da lista de livros que fizemos no passo anterior. Vamos criar a segunda página da nossa aplicação, começando pela requisição dos dados:

src/pages/livro/[slug].js
import Starlight, { VisualContent, Image } from '@starlightcms/next-sdk'
import Link from 'next/link'

// Essa função rodará sempre que acessarmos a rota "/livro/slug-de-um-livro".
export const getServerSideProps = async ({ params }) => {
// Agora, estamos requisitando o conteúdo de um livro com um slug específico.
// A propriedade "params.slug" é populada pelo Next.js. É por isso que nosso arquivo se chama "[slug].js".
// Se você utilizou outro slug no seu modelo, coloque-o no lugar de "books" na linha abaixo.
const response = await Starlight.books.entries.get(params?.slug)

return {
props: {
// Assim como na página inicial, só precisamos do conteúdo do livro, que está na propriedade "data".
book: response.data,
}
}
}

Note que a grande diferença é que nós estamos usando o método get() ao invés de list() do SDK do Starlight para requisitar um livro em específico. Agora, só precisamos criar o componente React que renderiza a página:

Dica

Esse exemplo contém o código completo do arquivo. Ganhe tempo copiando e colando esse conteúdo no seu arquivo local.

src/pages/livro/[slug].js
import Starlight, { VisualContent, Image } from '@starlightcms/next-sdk'
import Link from 'next/link'

const Book = ({ book }) => (
<main className="container mx-auto">
<article className="flex flex-col items-center p-5 m-5 bg-white rounded-lg shadow-md">
{/* Capa do livro */}
<figure className="w-32 mb-4">
{/* O componente Image renderiza uma imagem com todos os metadados (height, width e alt)
automaticamente preenchidos utilizando dados retornados pela API do Starlight. */}
<Image media={book.data.cover_picture} className="rounded" />
</figure>
<div className="flex flex-col items-center">
{/* Título do livro */}
<h1 className="text-3xl font-bold mb-2">{book.title}</h1>

{/* Número ISBN */}
<p className="text-gray-500 mb-2">{book.data.isbn}</p>

{/* Disponibilidade */}
<p className="mb-5">{book.data.is_available ? 'Disponível para compra.' : 'Indisponível.'}</p>

{/* O campo "Resumo" do nosso livro é um campo de editor visual, que é retornado pela API
do Starlight como um objeto JSON. O componente VisualContent transforma esse JSON em HTML. */}
<VisualContent content={book.data.excerpt} />

<hr className="w-full border-1 border-gray-200 my-5"/>

<Link href="/">⬅️ Voltar à lista de livros</Link>
</div>
</article>
</main>
)

// Essa função rodará sempre que acessarmos a rota "/livro/slug-de-um-livro".
export const getServerSideProps = async ({ params }) => {
// Agora, estamos requisitando o conteúdo de um livro com um slug específico.
// A propriedade "params.slug" é populada pelo Next.js. É por isso que nosso arquivo se chama "[slug].js".
// Se você utilizou outro slug no seu modelo, coloque-o no lugar de "books" na linha abaixo.
const response = await Starlight.books.entries.get(params?.slug)

return {
props: {
// Assim como na página inicial, só precisamos do conteúdo do livro, que está na propriedade "data".
book: response.data,
}
}
}

export default Book

E é só isso que precisamos fazer. Você pode acessar essa página ao clicar em qualquer livro na página inicial da sua aplicação.


Isso conclui o processo de criar uma aplicação simples que exibe o conteúdo que salvamos no Starlight. Se quiser, você pode criar ou editar conteúdo no Starlight para fins de teste. Para ver as mudanças na sua aplicação, basta recarregar a página no seu navegador.

Na próxima página, vamos enviar nossa aplicação para a nuvem em poucos minutos, e poderemos mostrar nossa aplicação funcionando ao vivo para qualquer pessoa na internet.