MMA LiveSim
DraftKings용 무료 UFC DFS 최적화와 MMA 전투 시뮬레이터, 실시간 승률·전후 기대값·소유율·최적 라인업 제공
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Weekly New England Patriots and UCLA Bruins column — Pros & Cons recaps, previews, and takes. Markdown posts compiled to a static site with Astro 7, Tailwind 4, and almost no client-side JavaScript.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A weekly New England Patriots column, published as a static site.
Live at patonsports.com.
Every game gets a Pros & Cons recap — what worked, what didn't, what it means for the rest of the season. The archive covers the full 2025 Patriots run from the opener in Las Vegas through the playoffs, plus UCLA Bruins recaps as the 2026 college season goes.
A Markdown folder that compiles to a website. Posts live in posts/, one file
per article, and Astro renders every route to static HTML at build time.
The design constraint the whole thing is built around: pages are static HTML
and JavaScript is the exception. Only two components hydrate in the browser —
the header (search and filters) and the comment thread. Post pages, the
homepage, category and tag pages, Pros & Cons blocks and share buttons all ship
as plain HTML with no JavaScript at all. The site loads instantly on a phone,
stays fully readable with scripting disabled, and every rendering bug is
reproducible by opening the built file in dist/.
| Typed content | Every post is validated against a Zod schema at build time. A malformed date or a missing description fails the build instead of shipping. |
| Pros & Cons layout | The recap format is parsed out of plain Markdown headings and rendered into side-by-side panels — no special syntax to learn when writing. |
| Scorelines | W 27–20 badges from front-matter scores, falling back to parsing the score out of the post title for older posts. |
| Categories and tags | Posts sort into Pros & Cons, Preview, NFL or UCLA from their tags, each with its own page. Opponent tags get their own pages too. |
| Search and filters | Client-side, over titles, descriptions, tags and post bodies, driven by ?q= and ?category= so any filtered view is a shareable URL. |
| Related posts | Scored by shared opponent, category and season, so a Bills recap surfaces the other Bills games. |
| Homepage shelves | A featured lead, a latest feed, and a separate shelf for the 2025 playoff run. |
| Audio | Narrated recordings live on Vercel Blob; front matter carries the URL, byte length, and duration for the player and RSS enclosure. |
| Feeds and SEO | RSS, a sitemap, robots.txt, canonical URLs, Open Graph and Twitter cards, all generated. |
| App JSON API | Build-time /api/v1/posts.json, per-post detail, and manifest.json for the native apps — Zod-validated so a bad shape fails the build. |
| Push | Device tokens in Neon; POST /api/push/register / unregister from the app; POST /api/push/broadcast (secret-protected) sends via Expo when a new posts/*.md lands on main. |
| Comments | First-party threads on Neon Postgres via Vercel Functions. New commenters stay pending until approved. Moderation is at /admin/comments, and each new comment can email an approve/reject link. |
Astro 7 · React 19 (two islands) · TypeScript 5 strict · Tailwind CSS 4 · Vitest · deployed on Vercel · Node 24.
nvm use # Node 24, pinned in .nvmrc
npm install
vercel link && vercel env pull .env.local # for comments + audio upload
npm run dev # http://localhost:4321
Static pages work with no env file. Comments, admin, push broadcast, and
upload-audio need the server vars in .env.local (see .env.example),
including PUSH_BROADCAST_SECRET for POST /api/push/broadcast. Public vars:
PUBLIC_SITE_URL, PUBLIC_TWITTER_SITE, PUBLIC_COMMENTS_API_BASE
(app manifest), and PUBLIC_APP_BANNER_MESSAGE (optional app banner).
A new comment emails COMMENT_NOTIFY_TO through Resend.
The message includes the post title and link, the commenter name, and the
comment text as plain text (HTML is escaped, and URLs in the comment are not
clickable). Approve and Reject open a confirmation page; the comment does not
change until the button is pressed. Each link is an HMAC signed with
COMMENT_APPROVAL_SECRET, stored only as a hash, and works once for 7 days.
The comment is saved even when Resend is down or the mail env vars are unset. That failure is logged and does not change the HTTP response.
Set these on Vercel as encrypted server env vars (Production, and Preview if
preview deployments should send mail). Do not use the PUBLIC_ prefix.
| Variable | Value |
|---|---|
RESEND_API_KEY | Resend API key with sending access |
COMMENT_NOTIFY_TO | Inbox that receives new-comment mail. Comma-separated for more than one. |
COMMENT_NOTIFY_FROM | Verified sender, e.g. Pat on Sports <[email protected]> |
COMMENT_APPROVAL_SECRET | Long random secret (openssl rand -base64 32) |
Resend only delivers from a verified domain. Add the domain used in
COMMENT_NOTIFY_FROM (for example patonsports.com) and publish the DNS
records Resend shows, including DKIM. The sandbox sender
[email protected] only delivers to the Resend account email, so it is
not a production from-address. Approve links use PUBLIC_SITE_URL.
Apply the comment_moderation_tokens migration (npm run db:migrate) before
relying on the links. Existing comments stay as they are: approved rows stay
approved, and new comments still default to pending. Public reads still return
only approved comments. Approving or rejecting deletes that post's comment
cache tag so the 15-minute CDN cache refreshes without waiting it out.
| Command | What it does |
|---|---|
npm run dev | Dev server with hot reload at localhost:4321 |
npm run build | Production build into dist/ |
npm run preview | Serve the production build locally |
npm run lint | astro check — typechecks the app and validates every post |
npm run test | Vitest in watch mode |
npm run test:run | Vitest once (what CI runs) |
npm run test:coverage | Coverage report |
npm run new-post -- ./export.zip | Convert a Google Doc export into a Markdown post |
npm run upload-audio -- ./recording.m4a --post <slug> | Upload a recording to Vercel Blob and write front matter |
npm run db:migrate | Apply Drizzle migrations (needs DATABASE_URL in .env.local) |
astro preview does not run the Vercel adapter's on-demand routes. Use npm run dev (with .env.local) or vercel dev to exercise /api/* and /admin/*.
Drop a Markdown file in posts/. The filename is the URL slug — no registry to
update, no index to regenerate.
---
title: "Week 1 Pros & Cons: Patriots 27, Seahawks 20"
date: 2026-09-10
description: "One sentence — the card blurb, the meta description, and the RSS summary."
tags:
- NFL
- "Pros & Cons"
- "Seattle Seahawks"
heroImage: "/images/2026/prosandcons/week-01/pats-vs-seahawks-hero.jpg"
heroAlt: "Describe the photograph for a screen reader"
season: 2026
week: 1
opponent: "Seattle Seahawks"
scoreUs: 27
scoreThem: 20
result: "W"
---
Content here.
title, date, description and tags are required. The rest is optional but
earns you the scoreline badge, the homepage shelf placement, and better related
posts. Full schema: src/content.config.ts. Full guide:
CONTRIBUTING.md.
Tags decide the category — see getCategory() in src/lib/posts.ts.
posts/ # the blog itself — one Markdown file per post
public/images/ # hero images, by season and week
src/
├── pages/ # file-based routes (index, blog, category, tag, rss, robots)
├── layouts/ # BaseLayout — <head>, nav, footer, SEO
├── components/ # .astro components + the two React islands
├── lib/ # posts.ts and prosCons.ts — where the real logic lives
├── content.config.ts # the Zod schema every post is validated against
└── styles/global.css # Tailwind v4 entry and theme tokens
scripts/ # Google Docs export → Markdown converter
test/ # shared Vitest setup
src/lib/posts.ts is the file to read first. Sorting, tag and category
resolution, search matching, score parsing and related-post scoring all live
there, and it's the only part of the codebase with real accumulated edge cases —
legacy ?tag= URLs that still have to resolve, scores parsed out of titles
written before the front-matter fields existed.
Every push and pull request runs typecheck and content validation, the test
suite, a production build, npm audit, CodeQL on security-extended, and a
gitleaks secret scan. Actions are pinned to full commit SHAs and the workflow
runs with contents: read.
main deploys to Vercel automatically; every PR gets a preview URL.
Corrections to a published post are especially welcome — there's an issue template for them. See CONTRIBUTING.md for everything else, and SECURITY.md to report a vulnerability privately.
Source code is MIT.
The editorial content — the posts under posts/ and the images under
public/images/ — is © 2026 Patrick Keenan, all rights reserved. Quote it with
attribution and a link, as you would any article. See
CONTENT_LICENSE.md.
Independent commentary. Not affiliated with the NFL, the New England Patriots, the NCAA, or UCLA.