Cozy Corner — by Gigi
voltar pra cozinha back to the kitchen
Passo 1 de 6 Step 1 of 6

Receita deste site Recipe for this site

Como cozinhei o Cozy Corner em 4 dias — How I cooked Cozy Corner in 4 days —
sozinha, com IA como co-piloto. solo, with AI as my co-pilot.

  • Tempo de preparo Prep time 4 dias 4 days
  • Serve Serves 1 designer · 1 marido · 1 gato (Akim) 1 designer · 1 husband · 1 cat (Akim)
  • Dificuldade Difficulty fácil (com os co-pilotos certos) easy (with the right co-pilots)
  • Rendimento Yield 1 site bilíngue, acessível, com dark mode, modo cozinha e cronômetro 1 fully bilingual, accessible site with dark mode, cooking mode, and a real timer
  • Fogo Heat um fim de semana focado one focused weekend

Ingredientes Ingredients

  • Astro v6.3.2
  • Cloudflare Pages (o forno) Cloudflare Pages (the oven)
  • JavaScript vanilla — sem React, sem Tailwind, sem framework noise Vanilla JavaScript — no React, no Tailwind, no framework noise
  • Phosphor Icons
  • Inter · Caveat · Cutive Mono (a tipografia) (the typography pairing)
  • Claude — pra código — for code
  • Gemini — pras ilustrações — for illustrations
  • Um fim de semana livre e um café forte A clear weekend and a strong coffee

O brief que dei pra mim mesma The brief I gave myself

Sou Product Designer há 6+ anos. Penso em fluxos, organizo sistemas, especifico telas — mas, na prática, quem fazia o trabalho aparecer no mundo era sempre outra pessoa. I've been a Product Designer for 6+ years. I think in flows, organize systems, spec screens — but in practice, someone else always made my work show up in the world.

Esse projeto começou de uma vontade simples: provar pra mim mesma que dava — eu, sozinha — pra desenhar, codar, escrever e deployar um produto inteiro, sem passar bastão. This project started from a simple itch: prove to myself I could — solo — design, code, write, and deploy a whole product, without passing the baton.

O escopo nasceu da minha rotina: meu marido e eu cozinhamos juntos toda semana, e nossas receitas viviam espalhadas em prints de WhatsApp e screenshots do Notes. Faltava um lugar bonito. Pronto, brief: site de receitas, com voz, em dois idiomas. The scope came from my routine: my husband and I cook together every week, and our recipes were scattered across WhatsApp screenshots and notes app captures. They deserved a real home. Brief locked: a recipe site, with voice, in two languages.

Referência Reference

inspiração principal main inspiration Alt. Portfolio por María Eugenia Solano · portfólio em formato de café by María Eugenia Solano · café-shaped portfolio

Adorei o conceito de espaço físico como navegação e peguei emprestado pro Cozy Corner. Café virou cozinha, cada elemento da cena vira hotspot pra uma categoria. O resto — modo cozinha, cronômetro, busca, voz, marca, o gato Akim — apareceu no caminho. I loved the concept of physical space as navigation and borrowed it for Cozy Corner. Café became kitchen, each scene element became a hotspot for a category. The rest — cooking mode, timer, search, voice, brand, Akim the cat — came along the way.

Passo 2 de 6 Step 2 of 6

Design System Design System

Princípios Principles

Cozy cream warm · nunca branco puro cream warm · never pure white
Narrativo Narrative 4 famílias tipográficas 4 typography families
Slow animações curvas · wipe 1.4s curved animations · 1.4s wipe
Tactile cozinha line-art · Akim mia line-art kitchen · Akim meows

Paleta Palette

Bicromática na prática: creme dominante + terracota como único acento usado com frequência. Em dark mode o creme vira navy e o terracota fica mais brilhante pra manter o calor. Bichromatic in practice: dominant cream + terracotta as the only frequently-used accent. In dark mode, cream becomes navy and terracotta gets brighter to keep the warmth.

--bg
light#FAF6EE dark#0F1A2A
--terracota
light#C56B4A dark#D58860
--ink
light#1A1A1A dark#F5F0E5

Tipografia Typography

Quatro famílias com papéis distintos. Caveat é exclusiva da marca; Inter carrega os títulos; Cutive Mono cobre body, UI e microcopy técnica. Four families with distinct roles. Caveat is brand-exclusive; Inter carries headings; Cutive Mono covers body, UI, and technical microcopy.

--font-brand só o logo logo only
Cozy Corner
--font-display títulos · clamp 22-96px titles · clamp 22-96px
Bolo de fubá com coco
--font-sans body, UI · 16px body, UI · 16px
Sempre uso essa massa
--font-mono meta · 13px meta · 13px
60 min · 8 porções · fácil

Spacing & Radius Spacing & Radius

base-4 · 8 níveis base-4 · 8 levels
--s-1 · 4
--s-2 · 8
--s-3 · 12
--s-4 · 16
--s-5 · 24
--s-6 · 32
--s-7 · 48
--s-8 · 64
4 valores fixos 4 fixed values
sm · 4
md · 8
lg · 16
pill

Motion Motion

--dur-fast150ms · hover, tap
--dur-base300ms · drawer, fade
--dur-slow600ms · transições maiores · larger transitions
intro wipe1400ms · cobertura inicial · initial cover

Easings sempre curvos (ease-out, ease-in-out, ease-spring) — nada de linear. 3 níveis de sombra reservados pra card sutil, drawer/dropdown e modal central. Easings always curved (ease-out, ease-in-out, ease-spring) — nothing linear. 3 shadow levels reserved for subtle card, drawer/dropdown, and central modal.

Acessibilidade Accessibility

A11y entrou como filtro de cada decisão: contraste AAA no texto principal, foco visível em todo interativo, navegação 100% por teclado, prefers-reduced-motion respeitado, alt texts escritos com intenção. A doc completa vive em /design-system com swatches light/dark lado a lado e mini-mockups de componentes reais. A11y was a filter on every decision: AAA contrast on body text, visible focus on every interactive, full keyboard navigation, prefers-reduced-motion respected, alt texts written with intent. Full docs live at /design-system with light/dark swatches side by side and mini-mockups of real components.

Passo 3 de 6 Step 3 of 6

Ilustração (Gemini) Illustration (Gemini)

A cena da cozinha line-art foi feita em camadas: Gemini gerou variações iniciais de cada objeto (geladeira, bancada, relógio, gato), e eu ajustei cada SVG manualmente pra refinar traços, garantir consistência de stroke-width, e amarrar todos os elementos no clima warm da paleta. The line-art kitchen scene was built in layers: Gemini generated initial variants of each object (fridge, counter, clock, cat), and I tuned each SVG by hand to refine strokes, ensure consistent stroke-width, and tie everything to the warm palette.

Cada objeto da cozinha virou hotspot interativo — não com retângulo invisível por cima, mas usando o bounding-box do próprio grupo SVG como hit-area. O relógio leva pras rápidas, a geladeira pras congelar, o gato é o Akim e abre uma mensagem própria. Each kitchen object became an interactive hotspot — not with an invisible rectangle on top, but using the SVG group's own bounding-box as the hit-area. The clock leads to quick recipes, the fridge to freezer recipes, the cat is Akim and opens his own message.

3 versões pra 3 tamanhos 3 versions for 3 screen sizes

A cena foi desenhada três vezes — não é o mesmo SVG escalado. Cada versão tem composição própria pra caber bem no aspect ratio do device. The scene was drawn three times — not the same SVG scaled. Each version has its own composition to fit the device's aspect ratio.

Desktop · ≥ 1024px Desktop · ≥ 1024px 1500 × 1000
z z Z
Tablet · 601 – 1023px Tablet · 601 – 1023px 991 × 1000
Mobile · ≤ 600px Mobile · ≤ 600px 460 × 1000 · 2 partes com scroll horizontal 460 × 1000 · 2 parts with horizontal scroll
Passo 4 de 6 Step 4 of 6

Traduções Translations

Demanda Demand

Trocar texto entre PT e EN na hora, sem reload, com pluralização correta (1 receita / 2 receitas) e algumas interpolações. Duas línguas, controladas por mim — sem time de tradução, sem CMS de strings. Swap text between PT and EN instantly, no reload, with correct pluralization (1 recipe / 2 recipes) and a few interpolations. Two languages, controlled by me — no translation team, no string CMS.

Solução Solution

~120 linhas de vanilla JS. Dicionário JSON aninhado + atributo data-t no HTML + um listener no toggle de idioma que percorre o DOM e troca textContent. Sem lib, sem build pipeline novo, sem overhead. ~120 lines of vanilla JS. Nested JSON dictionary + data-t attribute on HTML elements + one listener on the language toggle that walks the DOM and swaps textContent. No library, no new build pipeline, no overhead.

Por que não usar uma biblioteca Why not use a library

Olhei i18next, react-intl, o i18n nativo do Astro. Todos resolvem MUITO mais do que eu precisava — estrutura de pastas obrigatória, build pipeline novo, runtime overhead, conceitos pra aprender. Pra uma demanda trivial, o custo da lib era maior que o custo de escrever do zero. Looked at i18next, react-intl, Astro's native i18n. They all solve WAY more than I needed — required folder structures, new build pipelines, runtime overhead, concepts to learn. For a trivial need, the library cost was higher than writing it from scratch.

Tradução com DeepL + revisão manual DeepL drafts + manual review

DeepL rascunha as strings EN, eu reviso cada uma pra ajustar a voz. "Que tal apagar a luz?" virou "Care to turn off the light?", não "Want to turn off the lights?". Voz importa demais pra terceirizar 100%. DeepL drafts the EN strings, I review each one to tune the voice. "Que tal apagar a luz?" became "Care to turn off the light?", not "Want to turn off the lights?". Voice matters too much to fully outsource.

Trade-offs honestos Honest trade-offs

Não escala pra 5+ idiomas (sem fallback automático, sem lazy loading de dicionários, sem hot reload). Pra 2 idiomas controlados por mim, valeu cada linha não escrita. Doesn't scale to 5+ languages (no automatic fallback, no lazy loading of dictionaries, no hot reload). For 2 languages controlled by me, every unwritten line was worth it.

Passo 5 de 6 Step 5 of 6

Admin Admin

Demanda Demand

Editar receitas e ler mensagens do site sem servidor próprio, sem banco de dados, sem painel SaaS. Workflow simples: escrever → commitar → deploy automático. Edit recipes and read site messages with no server of my own, no database, no SaaS dashboard. Simple workflow: write → commit → automatic deploy.

Solução Solution

Decap CMS em /admin (Git-based, sem servidor) + Cloudflare Functions custom pra OAuth + interface própria em /admin-recados lendo do Cloudflare KV. Decap CMS at /admin (Git-based, no server) + custom Cloudflare Functions for OAuth + a separate interface at /admin-recados reading from Cloudflare KV.

Stack zero-infra Zero-infra stack

Tudo que eu edito no admin vira commit no GitHub via Decap CMS. O Cloudflare Pages detecta o push e refaz o build automaticamente — deploy pronto em segundos. Sem banco de dados, sem painel SaaS, sem custo recorrente. Roda local com npx decap-server pra desenvolver offline. Everything I edit in the admin becomes a GitHub commit via Decap CMS. Cloudflare Pages detects the push and rebuilds automatically — deploy ready in seconds. No database, no SaaS dashboard, no recurring cost. Runs locally with npx decap-server for offline development.

Dashboard — lista de receitas Dashboard — recipe list

Depois de logar, caio na lista de receitas. Cada item mostra título + categorias (sobremesas, congelar, vegetarianas, etc.). Sidebar com as duas coleções (Receitas e Páginas), Quick add no topo. Filter, sort e busca embutidos pelo próprio Decap. After logging in, I land on the recipe list. Each item shows title + categories (desserts, freezer, vegetarian, etc.). Sidebar with the two collections (Recipes and Pages), Quick add at the top. Filter, sort, and search are built into Decap.

Dashboard do Decap CMS — lista de receitas com sidebar de coleções, botões de filtro e ordenação
screenshot pendente screenshot pending admin-decap.png
/admin · dashboard com a lista de receitas /admin · dashboard with the recipe list

Como adicionar uma receita How to add a recipe

Click em "New Receita" abre o editor com todos os campos do schema configurado no config.yml: título, descrição curta, categorias, tempo em minutos (default 30), porções, dificuldade (fácil/médio/difícil), sistema de unidades (métrico/imperial), tags de filtro, mídia (fotos e vídeos), ingredientes, modo de preparo. Salvar dispara o workflow editorial (rascunho → revisão → publicado), commitando no GitHub e disparando rebuild automático no Cloudflare Pages. Clicking "New Receita" opens the editor with every field from the schema in config.yml: title, short description, categories, time in minutes (default 30), servings, difficulty (easy/medium/hard), unit system (metric/imperial), filter tags, media (photos and videos), ingredients, instructions. Saving triggers the editorial workflow (draft → review → published), committing to GitHub and triggering an automatic rebuild on Cloudflare Pages.

Editor de nova receita no Decap CMS — campos visíveis: título, descrição curta, categorias, tempo, porções, dificuldade, sistema de unidades, tags, mídia
screenshot pendente screenshot pending admin-decap-editor.png
/admin · editor de nova receita (campos do schema) /admin · new recipe editor (schema fields)

OAuth via Cloudflare Functions OAuth via Cloudflare Functions

A peça que precisei codar foi a autenticação. O Decap precisa de OAuth com o GitHub, mas o fluxo padrão assume hospedagem na Netlify. Como uso Cloudflare Pages, escrevi dois Cloudflare Functions custom (auth.js + callback.js) que fazem o handshake direto. Bônus: um proxy pra api.github.com porque alguns ISPs bloqueiam acesso direto à API. The piece I had to code was authentication. Decap needs OAuth with GitHub, but its default flow assumes Netlify hosting. Since I use Cloudflare Pages, I wrote two custom Cloudflare Functions (auth.js + callback.js) handling the handshake directly. Bonus: a proxy for api.github.com because some ISPs block direct API access.

Interface própria pros recados Custom interface for messages

As mensagens do formulário de contato vivem no Cloudflare KV (chave-valor edge-native — zero infra de banco). Pra ler com conforto, fiz uma interface separada em /admin-recados, com a mesma marca, leitura cronológica e marcação de lidas. Contact form messages live in Cloudflare KV (edge-native key-value — zero database infra). To read them comfortably, I built a separate interface at /admin-recados with the same branding, chronological reading and read-status marking.

Tela de entrada de /admin-recados — fundo creme com input de token de acesso
screenshot pendente screenshot pending admin-recados.png
/admin-recados · tela de entrada (token gate) /admin-recados · entry screen (token gate)
Passo 6 de 6 Step 6 of 6

Conclusões finais Final conclusions

O que a IA cozinhou — e o que ela não conseguiu What AI cooked — and what it couldn't

→ O que eu fiz → What I owned

Decisões de marca e tom. A voz em PT e EN. Cada microinteração que importa. O julgamento de "isso é bom o suficiente" e "isso precisa voltar". Brand and tone decisions. The voice in both PT and EN. Every microinteraction that matters. The judgment of "this is good enough" and "this needs to go back".

→ O que a IA acelerou → What AI accelerated

Claude pra código — scaffold de componentes Astro, refatorações, scripts de build, pegando edge cases que eu não pensaria. Gemini pras ilustrações da cozinha — variações rápidas de cada objeto (fogão, geladeira, gato), depois ajustadas em SVG. Claude for code — scaffolding Astro components, refactors, build scripts, catching edge cases I wouldn't think of. Gemini for the kitchen illustrations — quick variants of each object (stove, fridge, cat), then hand-tuned in SVG.

→ O que a IA não conseguiu → What AI couldn't do

Decidir o tom. Sentir quando uma animação está "perto, mas não". Editar minha própria escrita pra voz consistente. Saber por que uma decisão técnica funciona pra esse projeto e não pra outro. Esses momentos ainda são meus. Decide the tone. Feel when an animation is "close, but not quite". Edit my own writing for consistent voice. Know why a technical decision works for this project and not another. Those moments are still mine.

Notas de degustação Tasting notes

O aha moment foi chocantemente simples: foi chocantemente rápido e chocantemente fácil. Não "a IA fez tudo" — eu desenhei cada decisão. Mas o gap entre "quero essa feature" e "a feature está no ar, polida" colapsou de semanas pra horas. Perguntas que me travariam por meio dia viram conversas de 2 minutos. The aha moment was shockingly simple: it was shockingly fast and shockingly easy. Not "AI did everything" — I designed every decision. But the gap between "I want this feature" and "the feature is live, polished" collapsed from weeks to hours. Questions that would stall me for half a day became two-minute conversations.

A lição que levo: o muro entre design e engenharia caiu. Não totalmente — ainda existe especialidade, ainda existem complexidades que pedem time inteiro. Mas pra projetos do tamanho do Cozy Corner, designer sozinho com IA boa não é fantasia. É terça-feira. E isso muda o que dá pra prototipar, o que dá pra propor, o que dá pra defender com prova em vez de Figma. The lesson I take: the wall between design and engineering came down. Not entirely — specialty still exists, complexity that demands a full team still exists. But for projects the size of Cozy Corner, one designer with good AI isn't a fantasy. It's a Tuesday. And that changes what you can prototype, what you can propose, what you can defend with proof instead of a Figma file.

Próximas fornadas Next batches

Receitas de verdade: tô subindo as nossas, devagar, no ritmo do que cabe num fim de semana. Se você quiser ser cobaia de teste da primeira leva, deixa um recado. Real recipes: I'm uploading ours slowly, at the pace of what fits in a weekend. If you want to be a test taster for the first batch, leave a note.

Próxima fornada: um app mobile. Mesmo método, terreno novo — quero ver até onde o fluxo design + IA leva quando o output é um app nativo, não um site. Next batch: a mobile app. Same method, new territory — I want to see how far the design + AI workflow goes when the output is a native app, not a site.

Deixa um recado Leave a note

Curtiu o que viu? Quer trocar ideia sobre design, IA, ou só falar oi — Liked what you saw? Want to chat about design, AI, or just say hi —

LinkedIn Email Email Recado no site Note on the site