Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,12 @@ PROJECT_STARS_TTL_SECONDS=3600
# TTL do resultado de batalha (battle-id). Um resultado já sorteado é imutável;
# o que se decide aqui é por quanto tempo o link compartilhado continua vivo.
BATTLE_TTL_SECONDS=2592000

# --- Duelo ---
# TTL do resultado de duelo (duel-id), mesma política do battle-id: resultado
# imutável, o TTL só decide por quanto tempo o link compartilhado continua vivo.
DUEL_TTL_SECONDS=2592000

# --- Speed Duel (ygo) ---
# TTL do resultado do Speed Duel (ygo-id), mesma política do battle-id.
YGO_TTL_SECONDS=2592000
173 changes: 94 additions & 79 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,122 +5,137 @@ All notable changes to this project will be documented in this file.
Format: [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)


## [0.2.0](2026-08-12)
## [0.3.0](2026-08-15)

### Components
### Duelo-yugioh

#### Features

- adds useEffect import and adds useEffect
- adds useRef, UserSearchInput import and removes useState import and adds inputRef, resolved and removes target
- navegação entre modos e arrastar-e-soltar por pointer events
- updates logic
- arena do speed duel estilo Duel Links (board, replay e poster)
- sistema de duelo v2 (motor, arbitro, board, replay e poster)


### App
### E2e

#### Features
#### Bug Fixes

- adds NotFound function and adds Link, Shell, translator import
- updates icon, layout
- testa producao no endereco publico, e cobre o cache onde ele e visivel
- sonda a protecao da Vercel antes da suite, e agrupa as majors de lint

#### Tests

### Lib
- espera a hidratacao antes de mandar Escape no pacote


### Deps-dev

#### Chores

- sobe vitest para 4.1.10 e tira a config de JSX que sobrou
- bump typescript from 5.9.3 to 7.0.2
- bump eslint from 9.39.5 to 10.8.1

#### Features

- adds baseUrl import and adds oauthConfig, clientId in oauth
### Deps

#### Bug Fixes

- removes baseUrl import and adds appBaseUrl, explicit and removes appBaseUrl in oauth
- regenera o package-lock e volta eslint e typescript ao par suportado

#### Chores

### CHANGELOG
- bump actions/checkout from 4 to 7 in the actions group

#### Documentation

- adds and import
### Home

#### Features

### General
- a landing cabe numa tela, com trama no fundo e as cartas na mao


### Pack

#### Features

- o rasgo revela o verso da carta, e a pagina atras fica borrada


### Art

#### Features

- adds Image, type import
- adds useState, AXES, type import
- adds searchUsers, useRef, UserSearchInput import and removes useState import and adds dynamic, GET and removes target and adds useState, useRef, useId
- adds checkCardRateLimit, type, getRedisClient import and adds discoverPool, pool and removes authHeaders, token
- o site passa a falar a lingua da carta
- levar a carta embora -- previa de link, baixar PNG e compartilhar
- a raridade se expressa em superficie e borda, nao so em simbolo
- mais arte, e a solda entre arte e moldura
- HP como heroi numerico do cabecalho
- serial como elemento de design, e o rodape redesenhado sem ele
- foil impresso reassado em quatro camadas
- foil holografico por camadas e aureola do elemento
- icones de tipo na interface
- derivacoes da carta de repositorio
- arranjo simetrico da pagina da carta
- radar de assinatura do perfil
- 18 tipos, escada de raridade do TCG, serial e explicacao dos status
- batalha, site bilingue e carta interativa
- arte original, renderizacao da imagem e rotas de card
- base Next.js, dominio de cartas e scoring
- troca os 18 icones de tipo pela v2, e a paleta segue junto


### Mobile

#### Bug Fixes

- inclinacao 3D da carta nunca chegou a aplicar
- corta o sangramento na tela, e devolve o pacote ao centro


### Brand

#### Features

- emblema do verso da carta como favicon, navbar e pacote

#### Documentation

- estado real depois da fase 1 do revamp
- plano do revamp visual e as decisoes que o travam
- secao de contribuicao no README
- README conciliado com o codigo
- concilia RFC e specs com os 18 tipos
- handoff da sessao com o contexto que nao esta no codigo
### Ci

#### Chores

- scaffold inicial do gitmon-cards
- mostra o escopo do token quando o pull falha


### General

#### Features

- credita os dois autores no rodape, e abre o README com a marca e os tipos

#### Documentation

- README em ingles, CONTRIBUTING proprio e templates de issue e PR
- registra por que o e2e esta vermelho e o que a esteira ensinou

#### CI/CD

- nao reprova PR de fork, e nomeia o ambiente que falta antes do deploy


### Contributors

Thank you to 2 community contributors:
Thank you to 3 community contributors:

@mcsscalabrin
- feat: foil holografico por camadas e aureola do elemento
- fix: inclinacao 3D da carta nunca chegou a aplicar
- docs: secao de contribuicao no README
- docs: README conciliado com o codigo
- docs: concilia RFC e specs com os 18 tipos
- feat: icones de tipo na interface
- feat: derivacoes da carta de repositorio
- docs: handoff da sessao com o contexto que nao esta no codigo
- feat: arranjo simetrico da pagina da carta
- feat: radar de assinatura do perfil
- feat: 18 tipos, escada de raridade do TCG, serial e explicacao dos status
- feat: o site passa a falar a lingua da carta
- feat: levar a carta embora -- previa de link, baixar PNG e compartilhar
- docs: estado real depois da fase 1 do revamp
- feat: a raridade se expressa em superficie e borda, nao so em simbolo
- feat: mais arte, e a solda entre arte e moldura
- feat: HP como heroi numerico do cabecalho
- feat: serial como elemento de design, e o rodape redesenhado sem ele
- feat: foil impresso reassado em quatro camadas
- docs: plano do revamp visual e as decisoes que o travam
- feat(home): a landing cabe numa tela, com trama no fundo e as cartas na mao
- feat(art): troca os 18 icones de tipo pela v2, e a paleta segue junto
- test(e2e): espera a hidratacao antes de mandar Escape no pacote
- fix(mobile): corta o sangramento na tela, e devolve o pacote ao centro
- feat: credita os dois autores no rodape, e abre o README com a marca e os tipos
- fix(e2e): testa producao no endereco publico, e cobre o cache onde ele e visivel
- docs: README em ingles, CONTRIBUTING proprio e templates de issue e PR
- ci: nao reprova PR de fork, e nomeia o ambiente que falta antes do deploy
- fix(e2e): sonda a protecao da Vercel antes da suite, e agrupa as majors de lint
- chore(deps-dev): sobe vitest para 4.1.10 e tira a config de JSX que sobrou
- fix(deps): regenera o package-lock e volta eslint e typescript ao par suportado
- feat(brand): emblema do verso da carta como favicon, navbar e pacote
- docs: registra por que o e2e esta vermelho e o que a esteira ensinou

@benogoulart
- feat(components): adds useEffect import and adds useEffect
- feat: adds Image, type import
- feat: adds useState, AXES, type import
- feat(app): adds NotFound function and adds Link, Shell, translator import
- docs(CHANGELOG): adds and import
- feat(app): updates icon, layout
- feat(components): adds useRef, UserSearchInput import and removes useState import and adds inputRef, resolved and removes target
- feat: adds searchUsers, useRef, UserSearchInput import and removes useState import and adds dynamic, GET and removes target and adds useState, useRef, useId
- fix(lib): removes baseUrl import and adds appBaseUrl, explicit and removes appBaseUrl in oauth
- feat(lib): adds baseUrl import and adds oauthConfig, clientId in oauth
- feat: adds checkCardRateLimit, type, getRedisClient import and adds discoverPool, pool and removes authHeaders, token

**Contributors:** @mcsscalabrin, @benogoulart
- feat(ygo): navegação entre modos e arrastar-e-soltar por pointer events
- feat(duelo-yugioh): updates logic
- feat(duelo-yugioh): arena do speed duel estilo Duel Links (board, replay e poster)
- feat(duelo-yugioh): sistema de duelo v2 (motor, arbitro, board, replay e poster)
- feat(pack): o rasgo revela o verso da carta, e a pagina atras fica borrada

@49699333
- chore(deps-dev): bump typescript from 5.9.3 to 7.0.2
- chore(deps-dev): bump eslint from 9.39.5 to 10.8.1
- chore(deps): bump actions/checkout from 4 to 7 in the actions group

**Contributors:** @mcsscalabrin, @benogoulart, @49699333
8 changes: 5 additions & 3 deletions PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ existe para produzir e explicar a carta. Ele **não** viaja junto: o PNG exporta
## Capabilities and Constraints

**O que existe hoje:** carta de perfil e de repositório, batalha 1v1 com
resultado imutável e compartilhável, site bilíngue PT/EN com toggle manual,
radar de assinatura do perfil, painel de derivações, abertura de pacote, foil
holográfico ao vivo seguindo o ponteiro.
resultado imutável e compartilhável, duelo 1v1 dirigido e Speed Duel completo
em arena estilo Duel Links (decks de devs do GitHub, fases, posições e
magias/armadilhas), site bilíngue PT/EN com toggle manual, radar de assinatura
do perfil, painel de derivações, abertura de pacote, foil holográfico ao vivo
seguindo o ponteiro.

**Restrições técnicas travadas:**

Expand Down
2 changes: 2 additions & 0 deletions app/[owner]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export default async function ProfilePage({ params }: Params) {
label={t("home.battle")}
placeholder={t("home.opponent")}
action={t("home.battleAction")}
ygoMode
modeLabels={{ battle: t("home.modeBattle"), ygo: t("home.modeYgo") }}
/>
</CardPanel>

Expand Down
42 changes: 42 additions & 0 deletions app/api/duel/[duelId]/image/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { loadDuel } from "@/lib/duel/store";
import { BATTLE_IMAGE_CACHE_CONTROL } from "@/lib/config";
import { DEFAULT_CARD_LOCALE, parseLocale } from "@/lib/i18n/dictionaries";
import { renderDuel } from "@/lib/og/renderDuel";
import { renderErrorCard } from "@/lib/og/renderError";

export const runtime = "nodejs";

/**
* Pôster do resultado, servido em `/duel/<id>.png` pelo rewrite.
*
* Mesma regra do pôster de batalha: resultado imutável, cache duro. O confronto
* genérico em `/duel/<a>/vs/<b>` é que não pode ser cacheado — sorteia de novo a
* cada visita.
*/
export async function GET(
request: Request,
{ params }: { params: Promise<{ duelId: string }> },
) {
const { duelId } = await params;
const locale = parseLocale(
new URL(request.url).searchParams.get("lang"),
DEFAULT_CARD_LOCALE,
);

const duel = await loadDuel(duelId);

if (!duel) {
const image = await renderErrorCard("duel_expired", duelId, locale);
return withHeaders(image, "public, max-age=60, s-maxage=60", 404);
}

const image = await renderDuel(duel, locale);
return withHeaders(image, BATTLE_IMAGE_CACHE_CONTROL);
}

function withHeaders(image: Response, cacheControl: string, status = 200): Response {
const headers = new Headers(image.headers);
headers.set("Cache-Control", cacheControl);
headers.set("Content-Type", "image/png");
return new Response(image.body, { status, headers });
}
Loading
Loading