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
74 changes: 74 additions & 0 deletions app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use client";

import { useEffect } from "react";
import Link from "next/link";
import { ArrowLeft, RotateCw, Zap } from "lucide-react";
import BrokenCableAnimation from "@/components/ui/BrokenCableAnimation";

export default function Error({
error,
unstable_retry,
}: {
error: Error & { digest?: string };
unstable_retry: () => void;
}) {
useEffect(() => {
console.error(error);
}, [error]);

return (
<section className="relative min-h-[calc(100vh-80px)] flex items-center justify-center overflow-hidden px-4 sm:px-6 lg:px-8 py-24">
<div className="absolute inset-0 -z-10 pointer-events-none">
<div className="absolute inset-0 bg-grid bg-grid-fade opacity-40" />
<div className="absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[400px] bg-danger/15 blur-[140px] rounded-full" />
<div className="absolute bottom-10 right-10 w-[300px] h-[300px] bg-bitcoin/15 blur-[120px] rounded-full" />
</div>

<div className="relative max-w-3xl mx-auto w-full text-center">
<BrokenCableAnimation
className="mx-auto w-full max-w-xl aspect-[3/2]"
ariaLabel="Animación de un cable cortado con chispas"
/>

<div className="mt-2 inline-flex items-center gap-2 px-3 py-1 rounded-full border border-border bg-white/5 text-xs font-mono tracking-wider text-foreground-muted">
<Zap size={12} className="text-danger" />
ERROR INESPERADO
</div>

<h1 className="mt-6 font-display text-5xl sm:text-6xl md:text-7xl font-bold tracking-tight leading-[1.05]">
Algo se <span className="text-gradient-bitcoin">rompió</span>
</h1>

<p className="mt-5 text-lg text-foreground-muted max-w-xl mx-auto leading-relaxed">
Hubo un cortocircuito de nuestro lado. Reintentá o volvé al inicio
mientras lo arreglamos.
</p>

<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
<button
type="button"
onClick={() => unstable_retry()}
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-full bg-bitcoin text-black font-semibold text-sm hover:bg-bitcoin/90 transition shadow-lg shadow-bitcoin/20"
>
<RotateCw size={16} />
Reintentar
</button>
<Link
href="/"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-full border border-border bg-white/5 text-foreground font-semibold text-sm hover:bg-white/10 transition"
>
<ArrowLeft size={16} />
Volver al inicio
</Link>
</div>

{error.digest && (
<p className="mt-10 text-xs font-mono text-foreground-subtle tracking-wider">
$ ref:{" "}
<span className="text-foreground-muted">{error.digest}</span>
</p>
)}
</div>
</section>
);
}
Binary file removed app/favicon.ico
Binary file not shown.
101 changes: 101 additions & 0 deletions app/global-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"use client";

import { useEffect } from "react";
import { Inter, Space_Grotesk, JetBrains_Mono } from "next/font/google";
import { RotateCw, Zap } from "lucide-react";
import BrokenCableAnimation from "@/components/ui/BrokenCableAnimation";
import "./globals.css";

const inter = Inter({
variable: "--font-inter",
subsets: ["latin"],
display: "swap",
});

const spaceGrotesk = Space_Grotesk({
variable: "--font-space-grotesk",
subsets: ["latin"],
display: "swap",
});

const jetbrainsMono = JetBrains_Mono({
variable: "--font-jetbrains-mono",
subsets: ["latin"],
display: "swap",
});
Comment on lines +9 to +25

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wrong CSS variable names for fonts — font-display and font-mono classes will silently fall back on the global error page.

The Tailwind 4 theme in globals.css resolves the font-display and font-mono utilities via var(--font-display) and var(--font-mono). Here the fonts are registered under different names (--font-space-grotesk, --font-jetbrains-mono), so those CSS custom properties are never injected onto <html>. Since global-error.tsx fully replaces the root layout, the root layout's font declarations don't apply — making this the only font setup that runs. The h1 at line 64 (font-display text-5xl...) and the monospace refs at line 91 will silently fall back to the system font stack.

🔧 Proposed fix
 const inter = Inter({
-  variable: "--font-inter",
+  variable: "--font-sans",
   subsets: ["latin"],
   display: "swap",
 });

 const spaceGrotesk = Space_Grotesk({
-  variable: "--font-space-grotesk",
+  variable: "--font-display",
   subsets: ["latin"],
   display: "swap",
 });

 const jetbrainsMono = JetBrains_Mono({
-  variable: "--font-jetbrains-mono",
+  variable: "--font-mono",
   subsets: ["latin"],
   display: "swap",
 });

As per coding guidelines: "Font tokens (--font-sans for Inter, --font-display for Space Grotesk, --font-mono for JetBrains Mono) are exposed in Tailwind 4."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const inter = Inter({
variable: "--font-inter",
subsets: ["latin"],
display: "swap",
});
const spaceGrotesk = Space_Grotesk({
variable: "--font-space-grotesk",
subsets: ["latin"],
display: "swap",
});
const jetbrainsMono = JetBrains_Mono({
variable: "--font-jetbrains-mono",
subsets: ["latin"],
display: "swap",
});
const inter = Inter({
variable: "--font-sans",
subsets: ["latin"],
display: "swap",
});
const spaceGrotesk = Space_Grotesk({
variable: "--font-display",
subsets: ["latin"],
display: "swap",
});
const jetbrainsMono = JetBrains_Mono({
variable: "--font-mono",
subsets: ["latin"],
display: "swap",
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/global-error.tsx` around lines 9 - 25, The font CSS custom properties are
named incorrectly: change the variable options on Inter, Space_Grotesk, and
JetBrains_Mono to the Tailwind tokens (--font-sans, --font-display, --font-mono)
and ensure those variables are injected onto the HTML element used in
global-error.tsx (use the generated inter.variable, spaceGrotesk.variable,
jetbrainsMono.variable classes on the root <html> wrapper) so Tailwind utilities
font-display and font-mono resolve correctly.


export default function GlobalError({
error,
unstable_retry,
}: {
error: Error & { digest?: string };
unstable_retry: () => void;
}) {
useEffect(() => {
console.error(error);
}, [error]);

return (
<html
lang="es"
className={`${inter.variable} ${spaceGrotesk.variable} ${jetbrainsMono.variable} h-full antialiased`}
>
<head>
<title>Falla crítica · La Crypta Dev</title>
</head>
<body className="min-h-full bg-background text-foreground">
<section className="relative min-h-screen flex items-center justify-center overflow-hidden px-4 sm:px-6 lg:px-8 py-16">
<div className="absolute inset-0 -z-10 pointer-events-none">
<div className="absolute inset-0 bg-grid bg-grid-fade opacity-40" />
<div className="absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[400px] bg-danger/15 blur-[140px] rounded-full" />
</div>

<div className="relative max-w-3xl mx-auto w-full text-center">
<BrokenCableAnimation
className="mx-auto w-full max-w-xl aspect-[3/2]"
ariaLabel="Animación de un cable cortado con chispas"
/>

<div className="mt-2 inline-flex items-center gap-2 px-3 py-1 rounded-full border border-border bg-white/5 text-xs font-mono tracking-wider text-foreground-muted">
<Zap size={12} className="text-danger" />
FALLA CRÍTICA
</div>

<h1 className="mt-6 font-display text-5xl sm:text-6xl md:text-7xl font-bold tracking-tight leading-[1.05]">
Se cayó <span className="text-gradient-bitcoin">todo</span>
</h1>

<p className="mt-5 text-lg text-foreground-muted max-w-xl mx-auto leading-relaxed">
Hubo una falla profunda en el sistema. Estamos al tanto. Probá
recargar en un momento.
</p>

<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
<button
type="button"
onClick={() => unstable_retry()}
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-full bg-bitcoin text-black font-semibold text-sm hover:bg-bitcoin/90 transition shadow-lg shadow-bitcoin/20"
>
<RotateCw size={16} />
Reintentar
</button>
<a
href="/"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-full border border-border bg-white/5 text-foreground font-semibold text-sm hover:bg-white/10 transition"
>
Volver al inicio
</a>
</div>

{error.digest && (
<p className="mt-10 text-xs font-mono text-foreground-subtle tracking-wider">
$ ref:{" "}
<span className="text-foreground-muted">{error.digest}</span>
</p>
)}
</div>
</section>
</body>
</html>
);
}
102 changes: 102 additions & 0 deletions app/hackathons/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ function medal(position: number | null): string {

function SponsorStrip({ sponsors }: { sponsors: Sponsor[] }) {
if (sponsors.length === 0) return null;
if (sponsors.length === 1) return <SponsorHero sponsor={sponsors[0]} />;

return (
<div className="mt-10 rounded-2xl border border-border bg-background-card/60 backdrop-blur-sm p-5 sm:p-6">
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-5 sm:gap-8">
Expand Down Expand Up @@ -174,6 +176,106 @@ function SponsorStrip({ sponsors }: { sponsors: Sponsor[] }) {
);
}

function SponsorHero({ sponsor }: { sponsor: Sponsor }) {
return (
<div
className="mt-10 relative overflow-hidden rounded-3xl border-2 border-[#ec1d6a]/40 p-8 sm:p-10 lg:p-12"
style={{
background:
"radial-gradient(ellipse at 20% 0%, rgba(236,29,106,0.22) 0%, transparent 55%), radial-gradient(ellipse at 100% 100%, rgba(168,85,247,0.18) 0%, transparent 55%), linear-gradient(135deg, rgba(15,17,28,0.95), rgba(5,7,14,0.98))",
}}
>
{/* ambient glows */}
<div
aria-hidden
className="pointer-events-none absolute -top-32 -left-24 h-80 w-80 rounded-full blur-3xl"
style={{ background: "rgba(236,29,106,0.25)" }}
/>
<div
aria-hidden
className="pointer-events-none absolute -bottom-24 -right-24 h-72 w-72 rounded-full bg-nostr/15 blur-3xl"
/>
{/* eyebrow strip */}
<div className="relative flex items-center gap-2 text-[10px] font-mono font-bold tracking-[0.3em] uppercase text-[#ec1d6a]">
<span className="h-1.5 w-1.5 rounded-full bg-[#ec1d6a] animate-pulse" />
Partner oficial · Bonus ARS
</div>

<div className="relative mt-6 grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-10 items-center">
{/* Logo block */}
<div className="lg:col-span-5 flex flex-col items-start gap-5">
<div className="relative inline-flex items-center justify-center rounded-2xl border border-[#ec1d6a]/30 bg-white/95 px-6 py-4 shadow-[0_0_60px_rgba(236,29,106,0.30)]">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={sponsor.logo}
alt={sponsor.name}
className="h-16 sm:h-20 w-auto object-contain"
/>
</div>
<span
className="inline-flex items-center gap-2 rounded-full border-2 px-4 py-2 font-display font-black text-sm uppercase tracking-wide"
style={{
borderColor: "rgba(236,29,106,0.60)",
background: "rgba(236,29,106,0.15)",
color: "#ff5d96",
}}
>
<Sparkles className="h-4 w-4" />
+2 puntos de bonus
</span>
</div>

{/* Copy + CTAs */}
<div className="lg:col-span-7">
<h3 className="font-display text-3xl sm:text-4xl lg:text-5xl font-black tracking-tight leading-[1.05]">
Pasá de{" "}
<span className="text-bitcoin">sats</span> a{" "}
<span style={{ color: "#ec1d6a" }}>ARS</span>
</h3>
<p className="mt-4 text-sm sm:text-base text-foreground-muted leading-relaxed max-w-xl">
Sin KYC, directo a tu cuenta. Integrá{" "}
<span className="font-semibold text-foreground">{sponsor.name}</span>{" "}
en tu proyecto y sumás{" "}
<span className="font-bold" style={{ color: "#ff5d96" }}>
2 puntos más
</span>{" "}
al puntaje final.
</p>

<div className="mt-7 flex flex-wrap items-center gap-3">
{sponsor.url && (
<a
href={sponsor.url}
target="_blank"
rel="noopener noreferrer sponsored"
className="group inline-flex items-center gap-2.5 rounded-2xl px-6 py-3.5 font-display font-black text-base uppercase tracking-wide text-white shadow-[0_0_40px_rgba(236,29,106,0.45)] hover:shadow-[0_0_60px_rgba(236,29,106,0.65)] hover:scale-[1.03] active:scale-[0.97] transition-all"
style={{
background:
"linear-gradient(135deg, #ec1d6a 0%, #ff5d96 100%)",
}}
>
Probar {sponsor.name}
<ExternalLink className="h-4 w-4 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-transform" />
</a>
)}
{sponsor.docs && (
<a
href={sponsor.docs}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 rounded-2xl border-2 border-[#ec1d6a]/40 bg-[#ec1d6a]/[0.06] px-5 py-3.5 font-display font-black text-sm uppercase tracking-wide text-[#ff5d96] hover:border-[#ec1d6a]/70 hover:bg-[#ec1d6a]/[0.12] transition-all"
>
<BookOpen className="h-4 w-4" />
Documentación
</a>
)}
</div>
</div>
</div>
</div>
);
}

export default async function HackathonPage({
params,
}: {
Expand Down
2 changes: 1 addition & 1 deletion app/hackathons/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ function FeaturedHackathon({
key={s.name}
src={s.logo}
alt={s.name}
className="h-7 sm:h-8 w-auto object-contain"
className="h-14 sm:h-16 w-auto object-contain"
loading="lazy"
/>
))}
Expand Down
Binary file added app/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { Metadata } from "next";
import Link from "next/link";
import { ArrowLeft, Zap } from "lucide-react";
import BrokenCableAnimation from "@/components/ui/BrokenCableAnimation";

export const metadata: Metadata = {
title: "404 — Cable cortado",
description: "La página que buscás se desconectó del aire.",
robots: { index: false, follow: false },
};

export default function NotFound() {
return (
<section className="relative min-h-[calc(100vh-80px)] flex items-center justify-center overflow-hidden px-4 sm:px-6 lg:px-8 py-24">
<div className="absolute inset-0 -z-10 pointer-events-none">
<div className="absolute inset-0 bg-grid bg-grid-fade opacity-40" />
<div className="absolute top-1/3 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[700px] h-[400px] bg-bitcoin/15 blur-[140px] rounded-full" />
<div className="absolute bottom-10 right-10 w-[300px] h-[300px] bg-nostr/15 blur-[120px] rounded-full" />
</div>

<div className="relative max-w-3xl mx-auto w-full text-center">
<BrokenCableAnimation
className="mx-auto w-full max-w-xl aspect-[3/2]"
ariaLabel="Animación de un cable cortado con chispas"
/>

<div className="mt-2 inline-flex items-center gap-2 px-3 py-1 rounded-full border border-border bg-white/5 text-xs font-mono tracking-wider text-foreground-muted">
<Zap size={12} className="text-bitcoin" />
NOT FOUND
</div>

<h1 className="mt-6 font-display text-7xl sm:text-8xl md:text-9xl font-bold tracking-tight leading-[1] tabular-nums">
<span className="text-gradient-bitcoin">404</span>
</h1>

<p className="mt-4 font-display text-2xl sm:text-3xl font-semibold text-foreground">
Cable cortado
</p>

<p className="mt-4 text-lg text-foreground-muted max-w-xl mx-auto leading-relaxed">
La página que buscás se desconectó del aire. Probá reconectarte desde
otro lado.
</p>

<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
<Link
href="/"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-full bg-bitcoin text-black font-semibold text-sm hover:bg-bitcoin/90 transition shadow-lg shadow-bitcoin/20"
>
<ArrowLeft size={16} />
Volver al inicio
</Link>
<Link
href="/hackathons"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-full border border-border bg-white/5 text-foreground font-semibold text-sm hover:bg-white/10 transition"
>
Ver hackatones
</Link>
</div>

<p className="mt-10 text-xs font-mono text-foreground-subtle tracking-wider">
$ status: <span className="text-danger">DISCONNECTED</span>
</p>
</div>
</section>
);
}
Loading