如何赢得任何黑客马拉松🚀🤑

2025-06-04

如何赢得任何黑客马拉松🚀🤑

黑客马拉松是学习新知识、结识新朋友和构建酷炫项目的好机会。我在黑客马拉松上结识了一些最好的朋友,仅靠奖金就支付了我的大学学费。我意识到,要想获胜,最需要的是两样东西:快速的反馈循环速度。让我向你展示我是如何优化这两点的,其中包括一个很棒的开源入门模板,你可以在下一次黑客马拉松中使用👀

搞笑动图

快速反馈回路

反馈循环是指从你写完一行代码到你的团队欢呼雀跃(或绝望🫠)之间的时间。加快反馈循环可以保持团队的积极性,并让你更快地进行迭代。

从开发环境迁移到生产环境通常是开发过程中最大的瓶颈,原因可能是部署缓慢,也可能是需要审批。幸运的是,黑客马拉松不会出现这种情况!你的开发环境可以是生产环境,而部署环境可以是本地机器。最好的方法是实时预览你的应用。这完全消除了部署的需要,并允许你尽快迭代。(这也消除了非技术人员复制你的开发环境的需要!)

虽然有很多方法可以实现这一点,但我更喜欢使用Livecycle。Livecycle有一个 Docker 扩展,让你只需单击一下即可共享你的 docker-compose 应用(比 ngrok 之类的工具还要简单!)。它是免费的,安装只需不到 2 分钟。安装 Livecycle Docker 扩展后,你会在 Docker Desktop Dashboard 中看到这个新页面:

Livecycle 仪表板

只需点击“分享”,您就会获得每个 Docker 容器的唯一 URL,您可以将其分享给您的团队。每个 URL 都会连接到您的本地容器,让您轻松分享进度!🚀

共享应用程序

速度

在时间是主要制约因素的情况下,您显然希望尽快行动。当浪费时间设置项目可能会让您损失很多钱时,拥有一个好的模板至关重要。我有一个用于大多数黑客马拉松项目的模板。它是一个monorepo,带有Next.js前端、Hono后端和 Postgres 数据库。它完全是 docker 化的,可以通过单个命令启动。它还包含一些其他好东西,例如TailwindShadcnUIPrisma。与Livecycle结合使用,这使我团队中的技术人员能够在不到 5 分钟的时间内上手,而非技术人员可以实时查看进度。

设置

如果您安装了 docker 和 docker-compose,则设置非常简单。

首先,克隆存储库并将目录更改为项目的根目录:

git clone https://github.com/Code42Cate/hackathon-starter.git
cd hackathon-starter
Enter fullscreen mode Exit fullscreen mode

重命名packages/database/.env.examplepackages/database/.env使用 docker-compose 启动一切:

docker-compose watch
Enter fullscreen mode Exit fullscreen mode

PS:docker-compose watch 基本上是 docker-compose up,但具有针对 api 和 web 应用程序的热重新加载功能!

推送数据库模式:

pnpm turbo db:push
Enter fullscreen mode Exit fullscreen mode

您已准备就绪!让我们仔细看看该模板提供的功能:

Next.js 前端

使用一个拥有良好生态系统且拥有众多熟练开发者的主流框架有很多优势,尤其是在没有时间教队友学习新框架的情况下。
您可以在 中找到完整的前端/apps/web。首先,索引页包含一个简单的 CRUD 表,可用于在数据库中创建、读取和删除用户:

增删改查

大多数黑客马拉松应用都截然不同,因此我尽可能精简了前端。首页仅包含表格和数据获取部分:

import { User, columns } from "./columns";
import { DataTable } from "./data-table";

async function getData(): Promise<User[]> {
  const data = await fetch("http://api:3000/users").then((res) => res.json());
  return data as User[];
}

export default async function Page() {
  const data = await getData();

  return (
    <main className="flex flex-col items-center py-4">
      <DataTable columns={columns} data={data} />
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

最值得注意的是,数据的获取是通过 完成的fetch("http://api:3000/users")。这是因为前端和后端分别在不同的 Docker 容器中运行。api可以通过web容器访问 容器api:3000

ShadcnUI组件库

ShadcnUI是一个很棒的开源组件库,其中包含一些非常高质量的组件。您可以在此页面找到所有组件。如果您找到想要使用的组件,可以通过复制粘贴/packages/ui或运行以下命令手动添加:

pnpm turbo ui:add <component-name> # for example, accordion
Enter fullscreen mode Exit fullscreen mode

ShadcnUI 的使用完全是可选的,但如果你找到可用的工具,它可以为你节省大量时间。如果你不想使用它,直接忽略它就好🫣

Postgres 数据库

我使用 Postgres 作为数据库。并非因为它是最好的数据库,而是因为它是我最熟悉的。您可以随意使用任何您想要的!数据库使用 docker-compose 启动,并可在 上访问localhost:5432。为了简单起见,凭证在 中定义docker-compose.yml,并进行了硬编码。您可以根据需要更改它们,但您可能有更重要的事情要做!

如果您想使用其他内容,则需要在docker-compose.yml文件以及packages/database/.envpackages/database/schema.prisma文件中进行更改。

其余一切仍应正常工作!

Prisma ORM

Prisma 是一个 ORM,允许你以类型安全的方式与数据库交互。它非常易于使用,并且拥有许多很酷的功能。你可以在 中找到完整的数据库架构/packages/database/schema.prisma。要使用它,只需像这样导入:

import { PrismaClient, User } from "database";
Enter fullscreen mode Exit fullscreen mode

如果您创建一个新的应用程序/包,您需要先将其添加到您的 package.json 中:

{
  ...
  "dependencies": {
    "database": "workspace:*"
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

如果您的类型在编辑器中不起作用,则可能需要pnpm install在项目根目录中运行。有关如何使用 Prisma 的示例代码,请查看下一部分!

Hono 后端

虽然您可以使用 Next.js 服务器操作完成 99% 的后端工作,但拥有一个随时可用的后端仍然很重要。Hono是一个超轻量级且易于使用的后端框架,即使您没有任何经验,也可以立即使用它

您可以在 中找到完整的后端/apps/api。所有路由均在 中定义/apps/api/src/index.ts。请记住,这是为了黑客马拉松而设,而非用于生产环境。如果您愿意,可以把所有内容放在一个文件中(我保证不会告诉你的老板)。

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { PrismaClient, User } from "database"; // our own database package (/packages/database)

// Connect to the postgres database with prisma
// The connection string is defined in docker-compose.yml in the api service.
// This should work out of the box unless you change the postgres setup
const client = new PrismaClient();

const app = new Hono();

// No one likes cors errors
app.use(
  "*",
  cors({
    origin: ["http://localhost:3000"],
  })
);

// Get all users
app.get("/users", async (c) => {
  const users = await client.user.findMany();
  return c.json(users);
});

// Create user
app.post("/users", async (c) => {
  const data = await c.req.json();
  const user = await client.user.create({ data: data as User });
  return c.json(user);
});

// Delete user by id
app.delete("/users/:id", async (c) => {
  const user = await client.user.delete({
    where: { id: Number(c.req.param("id")) },
  });
  return c.json(user);
});

// Start nodejs http server. Change this if you want to use something like cloudflare workers
serve(app);
Enter fullscreen mode Exit fullscreen mode

如您所见,它非常简单。您可以使用该client对象与数据库交互。该app对象是一个 Hono 应用,本质上是一个路由集合。您可以使用app.getapp.postapp.delete等定义路由。该c对象是请求的上下文。它包含请求和响应对象,以及一些辅助函数,例如c.json用于发送 JSON 响应。

当然,你可以在 Next.js 中获得完全相同的功能,但一些炒作驱动的开发也是乐趣的一部分,对吧?🙃

Docker🐳

我通常不太喜欢用 Docker 来做那些快速而粗糙的黑客马拉松项目,因为我觉得它会拖慢我的进度。然而,自从 Docker 发布以来docker-compose watch,我改变了主意!它基本上可以让你拥有一个非常简单的开发设置,并且开箱即用地支持热加载。让我们来看看具体的 Docker 设置:

# docker-compose.yml
services:
  web: # Next.js Frontend
    build:
      dockerfile: web.Dockerfile # Path to web Dockerfile
    ports:
      - "3000:3000" # Reachable on localhost:3000
    depends_on:
      - api # Start after the API
    develop:
      watch:
        - action: sync # Synchronize the files on your host ./apps/web with your containers /app/apps/web when any file changes in that path
          path: ./apps/web
          target: /app/apps/web
          ignore:
            - node_modules/
        - action: sync # Same as above but with component library
          path: ./packages/ui
          target: /app/packages/ui
          ignore:
            - node_modules/
        - action: rebuild # Rebuild if the package.json changes
          path: package.json
        - action: rebuild
          path: ./apps/web/package.json
  api:
    build:
      dockerfile: api.Dockerfile # Path to API Dockerfile
    ports:
      - "3001:3000" # Reachable on localhost:3001, or api:3000 from within the Docker network
    depends_on:
      - postgres # Start after the database
    environment:
      - DATABASE_URL=postgres://postgres:postgres@postgres:5432/hackathon # Hardcoded database credentials are usually a no-go, but totally fine in this situation
    develop:
      watch:
        - action: sync # Synchronize the files on your host ./apps/api with your containers /app/apps/api when any file changes in that path
          path: ./apps/api 
          target: /app/apps/api
          ignore:
            - node_modules/
        - action: rebuild # Rebuild container if the package.json changes
          path: package.json
        - action: rebuild
          path: ./apps/api/package.json
  postgres: # Postgres Database
    image: postgres:latest
    ports:
      - "5432:5432" # Reachable on localhost:5432 if you want to connect with something like DataGrip
    environment: # Again, usually not a good idea to use these hardcoded credentials but okay for a hackathon
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
Enter fullscreen mode Exit fullscreen mode

TL;DR:我们将前端、后端和数据库定义为服务。除了常规的 docker-compose 设置外,我们还添加了docker-compose watch支持热加载的配置!

两个 Dockerfiles(api.Dockerfileweb.Dockerfile)都位于项目的根目录中,并且经过优化以用于开发,而不是生产构建。

您不需要触摸它们,但这里有一个简短的解释:

# You might want to use a different node version if you need any special libraries
FROM node:20.5.1-alpine AS base

FROM base AS builder
# not necessarily needed but often the cause for weird bugs
RUN apk add --no-cache libc6-compat
RUN apk update
# Set working directory
WORKDIR /app
# We need turbo to work with the monorepo
RUN npm install -g turbo
COPY . .
# remove everything from the monorepo that is not needed
RUN turbo prune --scope=api --docker

# Add lockfile and package.json's of isolated subworkspace
FROM base AS installer
RUN apk add --no-cache libc6-compat
RUN apk update
WORKDIR /app

# First install the dependencies (as they change less often)
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN corepack enable && corepack prepare pnpm@8.6.2 --activate

RUN pnpm --version
RUN pnpm install --frozen-lockfile

# Build the project
COPY --from=builder /app/out/full/ .
# We could properly build the project here, but we don't need to because this isnt for production we want hot reloads :)
CMD pnpm dlx turbo run dev --filter=api
Enter fullscreen mode Exit fullscreen mode

Dockerfile 看起来可能有点复杂(确实如此),但主要原因在于 turborepo 和对良好缓存的需求。实际上,你只需要修改最后一行即可。它基于这个很棒的 Github Issue

Livecycle

正如开头提到的,Livecycle允许我们通过创建 ✨tunnels✨ 与团队和评委共享我们的 docker-compose 应用。这非常有用,因为它允许我们实时分享进度,而无需部署任何东西。它还允许非技术人员查看进度并提供反馈。由于它“只是”一个 Docker 扩展,因此它不包含在仓库中。您可以直接从Docker Hub安装它。

结论

最终,最重要的是快速行动,享受其中的乐趣。构建你自己的模板,并使用你熟悉的技术。创造一些酷炫的东西!

直到下一次,

乔纳斯:D

文章来源:https://dev.to/code42cate/how-to-win-any-hackathon-3i99
PREV
升级你的学习+数据结构和算法的示例学习计划
NEXT
如何 Docker 化和部署 Express.js API