blob: eab82ae0611225558de9f4fec85fd100fed86a71 [file]
import {translate} from '@docusaurus/Translate';
import { buildSlackEntryUrl } from '@site/src/components/slack-redirect/slack-attribution.logic';
// Permanent task pages for the Apache Doris Hackathon. The /course entry and
// the task pages read everything hackathon-specific from here, so the whole
// hackathon block can be switched off or changed without touching the course
// itself. Nothing here is tied to a date or a venue.
/** Shows the "Doris 101 | Hackathon" switch in the /course path card. */
export const HACKATHON_COURSE_TRACK_ENABLED = true;
export const HACKATHON_EVENT = {
name: translate({id: "landing.hackathonEvent.001", message: "Apache Doris Hackathon"}),
basePath: '/course/hackathon',
// Set to null to render a dashed "TBA" placeholder instead. The file and
// folder names are the published starter-kit artifact; they keep their
// original name so existing downloads and submissions stay valid.
starterKitUrl:
'https://github.com/morningman/demo-env/releases/download/for-hackathon/doris-hackathon-glasgow-2026.zip' as
string | null,
/** Folder the ZIP unpacks to. */
starterKitFolder: 'doris-hackathon-glasgow-2026',
/** Participants open a pull request that adds <their GitHub ID>/ under this folder. */
submitUrl: 'https://github.com/morningman/demo-env/tree/main/doris-hackathon-glasgow-2026' as string | null,
submitLabel: 'morningman/demo-env' as string | null,
/** Apache Doris Slack channel for questions, submissions and badges. */
slackChannel: '#dev',
} as const;
/** Tracked entry to the Apache Doris Slack (see developer_docs/slack-utm-convention.md). */
export const HACKATHON_SLACK_URL = buildSlackEntryUrl({
medium: 'website',
content: 'hackathon_task_page',
});
/**
* The Doris every task runs: one FE and one BE in a single container, with a
* MySQL client inside (see /community/developer-guide/all-in-one-image).
*/
export const HACKATHON_DORIS_IMAGE = 'apache/doris:all-in-one-4.1.3';
/** Compressed download of the image, per architecture. */
export const HACKATHON_DORIS_DOWNLOAD = '1.9 GB';
export const DORIS_PULL = `docker pull ${HACKATHON_DORIS_IMAGE}`;
export const DORIS_RUN = `docker run -d --name doris -p 9030:9030 -p 8030:8030 -p 8040:8040 ${HACKATHON_DORIS_IMAGE}`;
export const DORIS_SQL = 'docker exec -it doris mysql -uroot -h127.0.0.1 -P9030';
/** Runs a SQL file from the starter kit with the MySQL client inside the container. */
export function dorisLoad(file: string): string {
return `docker exec -i doris mysql -uroot -h127.0.0.1 -P9030 < ${file}`;
}
export type HackathonTaskCode = 'A1' | 'A2' | 'A3' | 'A4';
export interface HackathonTaskMeta {
code: HackathonTaskCode;
slug: string;
title: string;
duration: string;
/** Short pitch, used on the task tiles. */
pitch: string;
}
export const HACKATHON_TASKS: HackathonTaskMeta[] = [
{
code: 'A1',
slug: 'a1-hybrid-search',
title: translate({id: "landing.hackathonEvent.002", message: "Hybrid Search App"}),
duration: translate({id: "landing.courseExtra.hackathonEvent.001", message: "60–120 min"}),
pitch: translate({id: "landing.hackathonEvent.003", message: "Keywords, meaning and filters in one SQL query. Build a search box over the Apache Doris docs."}),
},
{
code: 'A2',
slug: 'a2-mcp',
title: translate({id: "landing.hackathonEvent.004", message: "Ask Doris with MCP"}),
duration: translate({id: "landing.courseExtra.hackathonEvent.002", message: "45–90 min"}),
pitch: translate({id: "landing.hackathonEvent.005", message: "Plug Doris into your AI assistant with the Doris MCP Server, and make it answer real questions with real SQL."}),
},
{
code: 'A3',
slug: 'a3-log-search',
title: translate({id: "landing.hackathonEvent.006", message: "Log Search Explorer"}),
duration: translate({id: "landing.courseExtra.hackathonEvent.003", message: "60–120 min"}),
pitch: translate({id: "landing.hackathonEvent.007", message: "A mini Kibana where everything is SQL: BM25 search, filters and live counts over 200,000 log lines."}),
},
{
code: 'A4',
slug: 'a4-agent-traces',
title: translate({id: "landing.hackathonEvent.008", message: "Agent Trace Explorer"}),
duration: translate({id: "landing.courseExtra.hackathonEvent.004", message: "60–120 min"}),
pitch: translate({id: "landing.hackathonEvent.009", message: "Store messy AI-agent JSON in a VARIANT column and query it like real columns. No schema migrations."}),
},
];
export function getHackathonTask(code: HackathonTaskCode): HackathonTaskMeta {
const task = HACKATHON_TASKS.find(item => item.code === code);
if (!task) {
throw new Error(`Unknown hackathon task ${code}`);
}
return task;
}
/** Site-relative route of a task page, e.g. /course/hackathon/a1-hybrid-search */
export function hackathonTaskPath(task: HackathonTaskMeta): string {
return `${HACKATHON_EVENT.basePath}/${task.slug}`;
}
/** Track B: one page for all six "docs to demo" tasks. */
export const HACKATHON_TRACK_B = {
code: 'B',
slug: 'track-b',
title: translate({id: "landing.hackathonEvent.010", message: "Docs to Demo"}),
duration: translate({id: "landing.courseExtra.hackathonEvent.005", message: "30–60 min"}),
pitch: translate({id: "landing.hackathonEvent.011", message: "Pick a feature page of the docs, run it on your local Doris, and add a step-by-step demo to it with a pull request."}),
} as const;
export function hackathonTrackBPath(): string {
return `${HACKATHON_EVENT.basePath}/${HACKATHON_TRACK_B.slug}`;
}
/** Every hackathon page, in the order the task switcher and the "All tasks" tiles show them. */
export interface HackathonPageLink {
code: string;
title: string;
duration: string;
path: string;
}
export const HACKATHON_PAGE_LINKS: HackathonPageLink[] = [
...HACKATHON_TASKS.map(task => ({
code: task.code,
title: task.title,
duration: task.duration,
path: hackathonTaskPath(task),
})),
{
code: HACKATHON_TRACK_B.code,
title: `${translate({id: "landing.hackathonEvent.012", message: "Track B · "})}${HACKATHON_TRACK_B.title}`,
duration: HACKATHON_TRACK_B.duration,
path: hackathonTrackBPath(),
},
];