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
1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"react-monaco-editor": "^0.59.0",
"react-syntax-highlighter": "^16",
"react-toastify": "^11.0.5",
"remark-gfm": "^4.0.1",
"sass": "^1.89.2",
"stream-browserify": "^3.0.0",
"styled-components": "^6.1.19",
Expand Down
174 changes: 174 additions & 0 deletions website/src/pages/hackathons.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import Layout from '@theme/Layout';
import { useState, useEffect } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import Card from '@site/src/components/UI/Card';
import Button from '@site/src/components/UI/Button';
import styles from './hackathons.module.scss';

const AWESOME_NEAR_URL = 'https://raw.githubusercontent.com/near/awesome-near/master/README.md';

const fetcher = (url) => fetch(url).then((res) => res.text());

function processMarkdownLinks(markdown) {
if (!markdown) return '';

let processed = markdown;

processed = processed.replace(
/\[([^\]]+)\]\(https:\/\/docs\.near\.org\/([^)]+)\)/g,
'[$1](/$2)'
);

processed = processed.replace(
/\[([^\]]+)\]\(https:\/\/docs\.near\.org\)/g,
'[$1](/)'
);

const footerIndex = processed.indexOf('*To add a tool');
if (footerIndex > -1) {
processed = processed.substring(0, footerIndex);
}

return processed;
}

const Hackathons = () => {
const [awesomeNearContent, setAwesomeNearContent] = useState('');
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const fetchContent = async () => {
try {
const markdown = await fetcher(AWESOME_NEAR_URL);
setAwesomeNearContent(markdown);
setLoading(false);
} catch (err) {
console.error('Failed to fetch awesome-near:', err);
setError('Failed to load Awesome NEAR content');
setLoading(false);
}
};

fetchContent();
}, []);

const processedContent = processMarkdownLinks(awesomeNearContent);

if (loading) {
return (
<Layout title="Building on NEAR" description="Helpful resource directory to get started">
<div className={styles.loadingContainer}>
<h1>Loading Resources...</h1>
</div>
</Layout>
);
}

return (
<Layout title="Building on NEAR" description="Helpful resource directory to get started">
<div className={styles.hackathonsPage}>
<div className={styles.container}>
<header className={styles.header}>
<h1 className={styles.title}>Building on NEAR</h1>
<p className={styles.subtitle}>
Helpful resource directory to get started
</p>
</header>

<section className={styles.mainContent}>
<h2>Getting Started</h2>

<div className={styles.topGrid}>
<Card className={styles.topCard} variant="icon" icon={<span className={styles.emoji}>🌿</span>}>
<h3>What is NEAR?</h3>
<ul>
<li><a href="/protocol/basics">NEAR Protocol Basics</a></li>
<li><a href="https://docs.near.ai/" target="_blank" rel="noopener noreferrer">NEAR AI Documentation</a></li>
<li><a href="https://docs.near-intents.org/near-intents" target="_blank" rel="noopener noreferrer">NEAR Intents</a></li>
<li><a href="/tutorials/auction/introduction">Mastering NEAR Tutorial</a></li>
</ul>
</Card>

<Card className={styles.topCard} variant="icon" icon={<span className={styles.emoji}>💬</span>}>
<h3>Developer Support</h3>
<p>
<a href="https://near.dev/telegram-chats" target="_blank" rel="noopener noreferrer">
Join the Telegram Developer Chats
</a>
</p>
</Card>

<Card className={styles.topCard} variant="icon" icon={<span className={styles.emoji}>🧑‍💻</span>}>
<h3>Need NEAR AI Credits?</h3>
<p>
<a href="https://www.notion.so/Requesting-NEAR-AI-Cloud-Credits-2deda22d7b6481aea8e1e30282efcb5e" target="_blank" rel="noopener noreferrer">
Request NEAR AI Cloud Credits
</a>
</p>
</Card>
</div>
</section>

<section className={styles.awesomeNearSection}>
<h2 className={styles.sectionTitle}>Awesome NEAR</h2>
{error ? (
<Card className={styles.errorCard}>
<p>{error}</p>
<Button href="https://github.com/near/awesome-near" target="_blank">
View on GitHub
</Button>
</Card>
) : (
<>
<div className={styles.awesomeNearContent}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
components={{
h1: ({ children }) => null,
h2: ({ children }) => <h2 className={styles.mdH2}>{children}</h2>,
h3: ({ children }) => <h3 className={styles.mdH3}>{children}</h3>,
table: ({ children }) => <table className={styles.mdTable}>{children}</table>,
thead: ({ children }) => <thead className={styles.mdThead}>{children}</thead>,
tbody: ({ children }) => <tbody className={styles.mdTbody}>{children}</tbody>,
tr: ({ children }) => <tr className={styles.mdTr}>{children}</tr>,
td: ({ children }) => <td className={styles.mdTd}>{children}</td>,
a: ({ href, children }) => {
const isExternal = href && (href.startsWith('http://') || href.startsWith('https://'));
return (
<a
href={href}
target={isExternal ? '_blank' : undefined}
rel={isExternal ? 'noopener noreferrer' : undefined}
className={styles.mdLink}
>
{children}
</a>
);
},
ul: ({ children }) => <ul className={styles.mdUl}>{children}</ul>,
li: ({ children }) => <li className={styles.mdLi}>{children}</li>,
code: ({ children }) => <code className={styles.mdCode}>{children}</code>,
hr: () => <hr className={styles.mdHr} />,
p: ({ children }) => <p className={styles.mdP}>{children}</p>,
}}
>
{processedContent}
</ReactMarkdown>
</div>
<div className={styles.awesomeNearFooter}>
<a href="https://github.com/near/awesome-near" target="_blank" rel="noopener noreferrer">
View and contribute to Awesome NEAR on GitHub →
</a>
</div>
</>
)}
</section>
</div>
</div>
</Layout>
);
};

export default Hackathons;
Loading
Loading