Skip to content

chore: housekeeping and documentation - #11

Open
Guajir0-code wants to merge 2 commits into
sourcevortex:mainfrom
Guajir0-code:chore/housekeeping-and-docs
Open

chore: housekeeping and documentation#11
Guajir0-code wants to merge 2 commits into
sourcevortex:mainfrom
Guajir0-code:chore/housekeeping-and-docs

Conversation

@Guajir0-code

Copy link
Copy Markdown

O que é

Correções pequenas reunidas a partir de uma leitura do código, nenhuma delas grande o bastante para um PR próprio, mais a documentação que faltava.

Organizado em três blocos abaixo. Cada item é independente — se algum não fizer sentido, dá para retirar sem afetar os demais.


Comportamento

HandleAppearance nunca foi registrada

app/Http/Middleware/HandleAppearance.php existe, lê o cookie appearance e o compartilha com a view raiz. Mas bootstrap/app.php só registrava HandleInertiaRequests e AddLinkHeadersForPreloadedAssets.

Resultado: useAppearance.ts grava o cookie (com o comentário // Store in cookie for SSR) e ninguém nunca o leu. $appearance chegava sempre nulo no Blade, que caía no padrão 'system'. Quem escolhia claro ou escuro explicitamente via o tema errado piscar a cada carregamento completo.

SSR ligado por hardcode

'ssr' => ['enabled' => true, 'url' => 'http://127.0.0.1:13714'],

Sem env(). Em qualquer ambiente onde o processo de SSR não esteja rodando — o que inclui composer dev, que não o inicia — toda requisição paga uma tentativa de conexão que falha antes de cair no render do cliente.

Passa a ser env('INERTIA_SSR_ENABLED', false).

WpCategoryService não filtrava por taxonomia

WpTerm::query()->where('slug', $slug)->first();

Slugs só são únicos dentro de uma taxonomia. Uma tag com o mesmo slug de uma categoria podia ser devolvida no lugar dela. Agora há join com wp_term_taxonomy e filtro por taxonomy = 'category'.

Dots do carrossel fixos em 5

-v-for="i in 5"
+v-for="i in totalCount"

totalCount já era calculado a partir de api.scrollSnapList(). Com menos de cinco destaques sobravam bolinhas que não levavam a lugar nenhum.

Busca disparada no blur

HeaderSearchForm.vue submetia uma busca completa sempre que o input perdia o foco e o valor tinha mudado. Clicar fora do campo virava requisição. Removido; o submit do formulário continua funcionando.

useAppearance com estado por instância

O ref era criado dentro da função, então cada chamada gerava um estado próprio. O header renderiza um ThemeButton para desktop e outro para mobile — os dois podiam discordar sobre o tema atual. Movido para escopo de módulo.


Limpeza

Sidebar.vue era um placeholder cinza em produção

<div class="h-[500px] w-full bg-gray-800"></div>

Renderizado em toda página desktop. Passa a não renderizar nada, com um comentário explicando o porquê. Um painel cinza falso comunica menos que uma coluna vazia.

Vale o registro: o tema WordPress que este projeto substitui preenchia essa coluna com um anúncio. Se essa posição voltar é decisão de quem mantém o site, e por isso deixei o comentário no arquivo em vez de simplesmente apagá-lo.

Citação do Inspiring nos props compartilhados

[$message, $author] = str(Inspiring::quotes()->random())->explode('-');

Computada em toda requisição, serializada em todo payload do Inertia, e renderizada em lugar nenhum. Removida, junto com o tipo correspondente em index.d.ts.

OR sem agrupamento explícito no scope de busca

$query->where('post_title', 'LIKE', ...)->orWhere('post_content', 'LIKE', ...);

Isto não é um bug hoje. Verifiquei dumpando o SQL gerado: o callScope do Laravel aninha automaticamente as condições que um scope nomeado adiciona, e a saída sai corretamente parentizada:

... and ("post_title" LIKE ? or "post_content" LIKE ?) and "post_type" = ? ...

Mas essa é uma propriedade de como o scope é invocado, não deste código. No dia em que a condição for copiada para dentro de uma query, a precedência do SQL faz o AND ganhar do OR e os filtros deixam de valer. O agrupamento explícito custa três linhas e remove a armadilha.


Documentação

README.md

O repositório não tinha nenhum. Ninguém sobe o projeto sem ler o código-fonte, porque o .env.example diz DB_CONNECTION=sqlite enquanto a aplicação exige um MySQL com as tabelas do WordPress populadas.

O README cobre stack, requisitos, instalação, o acoplamento com o WordPress, as convenções que vivem no conteúdo (categoria destaques, menu chamado Menu, slug da política de privacidade), como rodar os testes e os quatro comandos de qualidade.

Inclui também um aviso sobre rodar php artisan migrate contra o banco do WordPress: as migrations do esqueleto criam users, cache e jobs dentro do mesmo schema, e com CACHE_STORE=database o Laravel passa a escrever no banco do WP.

A dependência de Advanced Custom Fields

O subtítulo exibido na capa do post vem de wp_postmeta com meta_key = 'subtitle'. Esse campo é criado pelo ACF — o tema WordPress anterior o lia com get_field("subtitle").

Nenhum dos dois repositórios declarava isso em lugar nenhum. Se o campo for movido para dentro de um group ou repeater no ACF, o formato do meta_key muda e o subtítulo desaparece do site sem erro algum, em nenhum log.

Está documentado no README, com a orientação de começar a investigação pelo ACF caso o subtítulo suma.


Como validar

php artisan test
Tests: 12 passed (133 assertions)

vue-tsc --noEmit limpo. Nenhum teste novo aqui: os itens são pequenos e a suíte existente cobre as sete rotas, que continuam passando.

Impacto

  • Tema: quem tem preferência explícita salva para de ver o flash do tema errado.
  • SSR: desligado por padrão. Quem já rodava o processo precisa definir INERTIA_SSR_ENABLED=true. É a única mudança deste PR que exige ação em deploy.
  • Payload: quote some dos props compartilhados.
  • Visual: a coluna lateral do desktop deixa de exibir o bloco cinza.
  • Schema: nenhuma alteração de banco.
  • Rollback: reverter o commit.

Fora de escopo

O esqueleto de autenticação do Laravel não foi removido, apesar de o projeto não ter login próprio. Comecei a remover app/Models/User.php, UserFactory e a migration de users, e recuei: config/auth.php aponta para App\Models\User e HandleInertiaRequests::share() ainda chama $request->user(), que resolve o guard e o provider. Desatar isso significa decidir o que fazer com o prop auth.user — decisão de quem mantém o projeto, não limpeza de rotina, ainda mais considerando que um trabalho futuro sobre a barra de admin pode querer usar essa estrutura.

Os itens de higiene de WpAuthService (chamadas de Log::debug a cada requisição despejando conteúdo de cookie, query redundante, @unserialize sem allowed_classes) também ficaram de fora. Eles moram no mesmo arquivo que precisa de uma revisão mais séria da validação do cookie do WordPress, e tocá-lo duas vezes seria desperdício.

Guajir0-code and others added 2 commits August 5, 2026 10:10
The app points Eloquent at an existing WordPress database, so no migration
creates wp_posts, wp_users, wp_terms and friends. Any test that touched the
database therefore could not run, and the single feature test in the repo
(GET / asserting 200) failed on a missing database.

Add a schema builder for the wp_* tables the app reads, small row builders,
and smoke coverage for all seven routes in routes/web.php, including the
highlighted-post exclusion, search, and the published/scheduled filtering the
global scope is responsible for.

withoutVite() keeps the suite independent of `npm run build`.
ExampleTest is dropped: RoutesTest covers GET / properly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Small fixes collected from a read through the codebase, none of which warrant
a pull request of their own.

Behaviour:

* register HandleAppearance. It existed but was never added to the middleware
  stack, so the cookie the theme switcher writes was never read back and anyone
  who picked light or dark explicitly saw a flash of the other theme on every
  full page load
* Inertia SSR is now env driven and off by default. Hardcoding it to true means
  every request pays for a failed connection to 127.0.0.1:13714 whenever the SSR
  process is not running, which is the case under `composer dev`
* WpCategoryService filters by taxonomy. Slugs are only unique within a
  taxonomy, so a tag could be returned where a category was asked for
* carousel pagination dots follow the number of slides instead of a hardcoded 5
* the search input no longer fires a request on blur
* useAppearance keeps its ref at module scope, so the desktop and mobile theme
  buttons cannot disagree

Cleanup:

* Sidebar renders nothing instead of a 500px grey placeholder block
* drop the Inspiring quote from the shared Inertia props, and its type: it was
  computed on every request and never rendered
* group the OR in the search scope explicitly

Docs:

* README covering setup, the WordPress coupling, the conventions that live in
  content rather than code, and the testing story
* document the Advanced Custom Fields dependency. The post subtitle comes from
  a meta key that ACF owns; if the field is reconfigured the subtitle silently
  disappears with no error anywhere

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant