Pular para o conteúdo

Multi-page clássico

O template multi-page gera um site institucional com várias páginas. O modelo classico é o padrão: slash create <pasta> --template multi-page gera o mesmo projeto que --model classico. Ele tem início, sobre, serviços, equipe, contato e uma página para cada serviço.

Rode slash create <pasta> --template multi-page na pasta onde o projeto deve ficar. A saída é esta:

Projeto criado em <projeto>.
Próximos passos, dentro da pasta:
  slash check                     confere conteúdo, contraste e SEO
  slash approve                   libera o conteúdo fictício aprovado
  bun run dev                     servidor local
  slash verify --update-baseline  grava as bases visuais e verifica tudo
[saída: 0]

Cada página tem um arquivo em src/pages/, e src/routes.ts liga cada caminho à sua página. As rotas do modelo classico são:

CaminhoPágina
/Início
/sobre/Sobre
/servicos/Lista de serviços
/servicos/<slug>/Uma página por serviço
/equipe/Equipe
/contato/Contato
/404Página de erro 404

Todos os caminhos terminam com barra (/sobre/), exceto /404. O endereço de cada serviço sai do slug do item, então abertura-de-empresa vira /servicos/abertura-de-empresa/. Use a mesma forma nos links internos.

O menu tem cinco links: Início, Sobre, Serviços, Equipe e Contato. Eles estão em menu, em src/data/site.ts.

O texto do site fica em src/data/, e as páginas só montam as seções com esse texto:

  • origin.ts: os marcadores de origem do texto, claude(...), fictitious(...) e pending(...), e plain(...), que os tira para as páginas.
  • site.ts: nome, WhatsApp, GTM, menu, rótulos do rodapé e o SEO da home.
  • footer.ts: as colunas do rodapé.
  • collections/services.ts: os serviços.
  • pages/<página>.ts: o texto de cada página, com título e descrição (SEO).
  • index.ts: a lista de todos os arquivos de dados. O bun run gate percorre essa lista para achar conteúdo fictício ou pendente, então um arquivo de dados novo precisa entrar nela.

O código comum a todas as páginas fica em src/site/. Você não precisa editá-lo para trocar textos.

Os textos dos arquivos de dados vêm embrulhados em marcadores de origem, de origin.ts. claude(...) marca o que o Claude escreveu, fictitious(...) marca o que foi inventado para o exemplo e pending(...) marca o que a agência ainda precisa fornecer. plain(...) tira essas marcas para as páginas, então o texto que aparece no site é só o valor. A revisão dos marcadores está em Textos a revisar.

O rodapé tem duas colunas. A primeira, com o título «Páginas», repete o menu. A segunda, com o título «Serviços», tem um link para cada serviço da coleção. O arquivo footer.ts monta as duas:

src/data/footer.ts
import { serviceItems, services } from "./collections/services";
import { site } from "./site";
/**
* The link columns of the footer: the pages of the menu and one link per service. Data, so the layout stays the same
* in every model: a model with another collection replaces this file and nothing else. `plain(footerColumns)` strips
* the origin markers for the footer.
*/
export const footerColumns = [
{ title: site.footer.pagesTitle, links: site.menu },
{
title: site.footer.servicesTitle,
links: serviceItems.map((item) => ({ label: item.title, href: `${services.path}${item.slug}/` })),
},
] as const;

Os textos de cada página ficam em src/data/pages/. O exemplo abaixo é a página de serviços: o SEO (título e descrição), o cabeçalho, a lista, as perguntas e a chamada final:

src/data/pages/services.ts
import type { SeoInput } from "../../ui";
import { serviceCards } from "../collections/services";
import { claude, fictitious } from "../origin";
import { seo as homeSeo, WHATSAPP } from "../site";
/** SEO of /servicos: the share image and the theme come from the home. */
export const servicesSeo: SeoInput = {
...homeSeo,
title: "Serviços de contabilidade em Curitiba | Martins & Reis",
description:
"Abertura de empresa, contabilidade mensal, planejamento tributário e departamento pessoal: veja o que a Martins & Reis faz pela sua empresa.",
};
/** Sections of the services page (InstServicos), in page order. */
export const servicesContent = {
trail: { label: claude("Serviços") },
header: {
eyebrow: claude("Serviços"),
title: claude("Tudo o que a sua empresa precisa em contabilidade"),
intro: claude("Escolha um serviço para ver o que está incluído, como funciona e tirar as dúvidas mais comuns."),
},
services: { variant: "alternating", tone: "light", title: claude("Nossos serviços"), items: serviceCards },
faq: {
variant: "single",
tone: "gray",
title: claude("Dúvidas frequentes"),
items: [
{
question: claude("Vocês atendem empresas de qualquer porte?"),
answer: claude("Atendemos microempresas e pequenas empresas, de prestadores de serviço ao comércio."),
},
{
question: claude("Posso contratar só um dos serviços?"),
answer: claude("Pode. Cada serviço funciona sozinho, e você acrescenta outros quando precisar."),
},
{
question: claude("Como é o atendimento no dia a dia?"),
answer: fictitious("Respondemos pelo WhatsApp em até 4 horas úteis, de segunda a sexta."),
},
],
},
cta: {
variant: "band",
tone: "dark",
title: claude("Não achou o que procura?"),
text: claude("Conte a sua necessidade pelo WhatsApp e dizemos como podemos ajudar."),
cta: { kind: "whatsapp", label: claude("Chamar no WhatsApp"), href: WHATSAPP },
},
} as const;

serviceCards, em collections/services.ts, é a lista de cartões dos serviços (título, resumo, foto e link da página). A home e a página de serviços a usam. Ela sai de serviceItems, então um serviço novo aparece nela sem outra edição.

Cada item da coleção services vira um cartão na lista e uma página própria. O projeto sai com quatro serviços, todos no mesmo molde. Cada item tem:

  • slug: o endereço da página. Só letras minúsculas sem acento, números e hífens. Um slug vazio, repetido ou com acento impede o build, e a mensagem diz qual item e qual slug sugerido.
  • title e summary: o nome e o texto do cartão.
  • intro e seoDescription: o parágrafo de abertura da página e a descrição para o Google.
  • image: a foto do cartão e da página.
  • includes: o que está incluído no serviço.
  • steps: as etapas do trabalho, em ordem.
  • faq: as perguntas da página do serviço.

Para adicionar um serviço, copie um item de serviceItems em collections/services.ts e troque os campos. A página, o cartão, a coluna do rodapé e a entrada no sitemap saem sozinhos.

As páginas internas mostram uma trilha: Início, a seção e a página. A mesma trilha vai para os dados estruturados de cada rota. Os rótulos ficam no arquivo de dados da página. A home não tem trilha.

Valores marcados com claude(...), fictitious(...) ou pending(...) ainda precisam da sua revisão. Troque pelo texto real e tire o marcador. slash check confere conteúdo, contraste e SEO, e slash approve libera o conteúdo fictício que você aprovou.

Para uma página de uma só rolagem, veja One-page. Para um catálogo com preços e busca, veja Multi-page catálogo.