Vibe designers, thank me later.
Nutlope/hallmark
11 likes · 2,344 views
سایتهایی که با هوش مصنوعی میسازی چرا همهشون شبیه همن؟
- این اسکیل ۴۱ هزار ستاره داره و ۵۰ تم میده
- الگوهای تکراری رو قبل از انتشار میگیره
سایت تو هم این نشونهها رو داره؟
سایتش اینجاست: nutlope/hallmark
13 likes · 1 repost · 623 views
Hallmark checks AI-built pages for generic design habits. What would you test it against?
I'm Obi, the builder of RepoQuarry. This is our one-minute Hallmark overview, presented by Sky, whose image and voice are AI-generated.
Hallmark is a design skill made by Together AI, hosted at Nutlope/hallmark. The README describes a choice of three themes from fifty, layouts shaped around the page's actual purpose, and a browser checker called sloplint running at eight widths. It also describes credited, openly licensed photos and asking for real product facts instead of inventing them.
That is the documented workflow, not our test result. We've read the docs but haven't installed or run it. The skill is MIT licensed; you still need a coding agent and may pay for its plan or API usage. Browser checks need Chrome and puppeteer-core. Stars indicate interest, not a quality rating; the video's counts are dated 1 November.
Creator/source: Nutlope/hallmark
Official demo: usehallmark.com
RepoQuarry breakdown and requirements: repoquarry.dev
If you've tried design skills like this, what would be a fair test: an existing page redesign, an accessible booking flow, or the same brief across several agents?
reddit.com
1 point
Taste can't be linted. The tells can.
---
title: "Taste can't be linted. The tells can."
published: true
published_at: 2026-10-30 11:00 -0700
tags: webdev, ai, opensource, discuss
cover_image: beehiiv-images-production.s3.amazonaws.com
---
My product's homepage has six top-level headings. Every one has a small pill or a line of capitals above it, and every one ends on a word set in italic serif.
I didn't notice until I pointed a design lint's rules at the page. Two of the pills say phrases that appear word for word in the lint's source code.
The lint ships inside Hallmark, and it changed how I think about the "AI slop" complaint. You can't write a test for taste. You can write one for the tells.
A design skill with a script behind it
Hallmark is an MIT-licensed skill for Claude Code, Codex, Cursor and OpenCode, made by Hassan El Mghari (Nutlope) at Together AI. Version 2 (2.0.0 in its package.json) was merged on October 22. It was #1 on GitHub trending on Tuesday with 2,830 stars that day, and the GitHub API showed 39,048 stars when I checked that evening.
Most design skills are a long prompt. This one is a prompt plus machinery. SKILL.md opens with a 16-rule Floor no build may break, then a flow: read the project, ask once for real material, deal three themes, build and review the hero alone, then sweep the page. There are 50 themes (I counted 50 files and 50 preview images). The rules live in references/gates.md, and the checker is scripts/sloplint.mjs: 4,422 lines, zero dependencies, Node 18 and up.
Install is one line:
npx skills add nutlope/hallmark -g
The tells, written down as rules
gates.md is the file worth reading. It lists 90 numbered gates, each with a tier and a class. Floor gates never ship. Reflex gates are a model's defaults, and a build may waive one in a CSS comment with a real reason. Class M means the static script can settle it from CSS and markup; R needs a real browser; J is judgment at review time. I counted 45 M gates and 9 judged only.
The named tells read like things most of us have shipped: the eyebrow (a short line announcing the heading under it), the tracked-caps label, one coloured word in a headline, middle dots between meta items, a form that says "Thanks" while sending nothing. Four are "house rules" (the eyebrow, tracked caps, an 80-words-per-screen budget, template punctuation), which sit in the Floor with no waiver.
What sold me is how literal the script gets. This is how it decides a gradient is purple-to-blue:
const purple = stops.some((h) => hueIn(h, 265, 330));
const blue = stops.some((h) => hueIn(h, 200, 264));
// ...
if (purple && blue) return 'purple-to-blue';
Each stop is converted to OKLCH first, and only counts with chroma above 0.04, so a grey wash passes. transition: all is one regex. A tracked-caps label is uppercase, small caps or letter-spacing past 0.03em on anything named like a label (badge, meta, nav, caption and about twenty more) or set at 15px or under. An eyebrow is a short line before a heading with a class like kicker or badge, two style signals, or one of a fixed list of announcing phrases. It reads Tailwind class strings in .jsx, .tsx, .vue, .svelte and .astro files too, including cn() and clsx() calls.
I ran five of the rules on my own homepage
I didn't run sloplint. It's downloaded code, and I don't execute that for a post. I read the functions, ported five checks to about 100 lines of Python, and ran them on the HTML and CSS of somiibo.com, my product's homepage. The CSS is one 217 KB bundle: Bootstrap 5.3.6, then the site's own layer. My scripts print one line per finding; here is the tally:
transition: all 16 rules (15 site layer, 1 inline)
animated height/width 2 (Bootstrap's own .collapsing)
purple-to-blue gradient 7 rules, 2 in use (hero, pills)
tracked capitals 0
middle-dot strings 0
eyebrows 6 above 6 headings
accented word 6 of 6 headings
focus styles present (passes)
overflow-x: clip missing on html and body
The headings stung. Each h1 and h2 wraps its last word or two in <span class="text-accent">, an italic serif: "Grow your social media on autopilot", "Unlock your growth potential". Each also has an eyebrow: capitals over the h1, a pill over every h2. Two pills say "How it works" and "Get started", both on the lint's list.
The gradient is less clear-cut. The hero uses an eight-stop rainbow with #a166ab (hue 322 by my conversion) and #5073b8 (263) in it, so the rule calls it purple-to-blue, though no person would. The textbook case, #5b47fb to #00d4ff, sits in the same stylesheet, unused on this page. The static tier reads rules, not usage.
The passes were real: no positive letter-spacing anywhere, no text joining items with two middle dots, and focus styles exist.
I tried ianwiedenman.com too. Above my name sits "Hello, I'm" in a <p class="text-uppercase tracking-widest">, an eyebrow asking for tracked caps. But tracking-widest is a Tailwind class on a Bootstrap site, and neither of its stylesheets defines it, so the browser draws plain capitals. The glow behind it is three radial gradients whose custom properties are named --grad-purple-x, --grad-cyan-x and --grad-pink-x.
Why a lint beats a paragraph of taste
Here's my claim. "Make it look premium" in a prompt is a wish. A model can agree with it and has no way to check its output against it. "No stop between hue 265 and 330 beside one between 200 and 264" is a test. It fails a build, names a line, and doesn't get tired.
There's evidence this matters. In September a user, ktlesr, posted a measurement in issue #74 on an earlier version: four landing-page briefs built with and without the skill, scored by pattern checks. Pure black or white appeared on 40 of 40 pages without it and 14 of 28 with it. transition: all didn't drop (14 of 40 against 16 of 28). Their reading: that rule lived in a reference file the model never opened.
Version 2 reads like the answer. transition: all is now rule 2 of the Floor, in the file that always loads, and rule 16 tells the agent to run sloplint, when Node is available, and fix every FAIL before handing back. A rule in prose can be skipped. A script with an exit code can't, as long as something runs it.
Where a lint stops
A lint on tells is a floor, not a design. Strip the eyebrows and italic words from my homepage and it avoids a dozen mistakes, but it still has no idea of its own. Builds pushed away from the same defaults can also converge on a new shared look. In a July HN thread, mstkllah said design skills like this all end up in the same place unless you are very explicit. Hallmark's answer sits outside the lint: themes dealt from fifty, a log of past builds the deal avoids, and a reviewer subagent that reads the page cold. That part is judgment, and I didn't test it.
Some rules are opinions. "Never an eyebrow" and "never tracked caps" are house rules, so no waiver. A magazine that sets section labels in spaced small caps on purpose is breaking the Floor.
One rough edge in the source: --tier isn't validated. Pass --tier Floor with a capital F and the filter matches nothing, so the run prints clean and exits 0. PR #93 reported it and was closed unmerged; the commit I read (6033bab) still does it. My own checks were static only. The fold and anything measured on the rendered page need the render tier, which needs Chrome and puppeteer-core.
Try it on a page you already have
After the install, /hallmark audit ./index.html reports without redesigning anything. From a clone, the bare lint is node skills/hallmark/scripts/sloplint.mjs index.html. I haven't run either; I read the source and reproduced a few checks by hand.
One detail I liked: the photo library is 755 openly licensed pictures on Wikimedia Commons, credited on the page. The README says it skips Unsplash, Pexels and Pixabay because their terms bar AI tools from picking their images.
Which of these tells is on your own homepage right now, and is it there on purpose?
1 reaction
Bygga offers animated, step-by-step 3D guides for assembling IKEA furniture, using AI to scan and interpret paper manuals. The tool generates interactive instructions for over 1,171 products, allowing users to navigate each assembly process seamlessly. Nutlope/bygga
1 like
Hallmark คืออะไร? สกิลที่บังคับให้ AI ทำเว็บไม่ให้ดูเป็น AI
โดย Nokka (นก-กา) | ตรวจข้อมูล 29 ต.ค. 2026
บทความนี้เขียนโดย AI (deepseek-v4.1-flash · ผู้ให้บริการโมเดล: ollama-cloud) ผ่าน Hermes Agent ภายใต้การควบคุมและตรวจสอบคุณภาพโดยมนุษย์ - Nokka (นก-กา)
!ภาพประกอบ: หน้าเว็บหลายหน้าซ้อนกันโดยมีไม้บรรทัดและตารางวัดทาบอยู่ด้านบน
ถ้าคุณเคยให้ AI สร้างหน้าเว็บสักสิบหน้า คุณคงสังเกตเห็นอะไรบางอย่าง
มันดูคล้ายกันไปหมด ไล่ตั้งแต่หัวข้อตัวใหญ่ที่จัดกลาง ป้ายตัวเล็กตัวพิมพ์ใหญ่ห่างกันเหนือหัวข้อ ปุ่มมุมโค้งที่ไล่สีสวย แล้วปิดท้ายด้วยช่องกรอกอีเมล
ผมคิดว่าความเหมือนนี้ไม่ใช่เรื่องบังเอิญ มันออกมาจากที่เดียวกัน คือรูปแบบที่โมเดลเรียนจากหน้าเว็บจำนวนมหาศาล
ผมเจอเครื่องมือที่สร้างมาเพื่อสู้กับเรื่องนี้โดยเฉพาะจากคลิปของ @aijaidee10 [1] มันชื่อ Hallmark
Hallmark คืออะไร
Hallmark เป็นสกิลสำหรับ AI coding agent ใช้ได้กับ Claude Code, Codex, Cursor และ OpenCode [2]
จุดยืนของมันเขียนไว้ชัดในรีโป คือ "ปฏิเสธที่จะดูเหมือนงานที่ AI สร้าง" และมันทำงานโดยการบังคับกฎ แล้วปล่อยให้โมเดลทำงานต่อ [3]
ตัวเลข ณ วันที่ผมตรวจคือ 40,998 ดาว 2,126 forks สัญญาอนุญาต MIT สร้างเมื่อ 27 เม.ย. 2026 และอัปเดตล่าสุด 28 ต.ค. 2026 [2]
รีโปนี้พัฒนาโดยทีม Together AI ตามที่ระบุใน README [3]
กลไกที่ทำให้มันต่างจาก prompt สวย ๆ
สกิลออกแบบเว็บทั่วไปมักเป็นไฟล์ Markdown ที่บอกว่า "จงออกแบบให้สวย ทันสมัย อย่าใช้สีฉูดฉาด"
Hallmark ไม่ได้หยุดที่คำแนะนำ แต่มีด่านตรวจที่รันโค้ดจริง
ขั้นที่ 1: อ่านโปรเจกต์ก่อนออกแบบ
ก่อนเริ่ม มันจะอ่านโปรเจกต์เพื่อดูฟอนต์ ชุดสี เฟรมเวิร์ก และไฟล์ design.md ที่ถูกล็อกไว้ แล้วถามหาวัสดุจริงอย่างรูปถ่าย ภาพหน้าจอ และตัวเลขจริง [3]
จุดนี้สำคัญเพราะปัญหาหนึ่งของงาน AI คือการแต่งข้อมูลขึ้นมา ถ้าไม่มีข้อมูลจริง มันจะไม่ยอมแต่ง
ขั้นที่ 2: แจกธีมสามจากห้าสิบ
คำสั่ง theme.mjs deal จะเลือกธีมสามชุดที่เข้ากับโจทย์ และกันไม่ให้ซ้ำกับสามงานล่าสุดที่บันทึกไว้ใน log [3]
ธีมแต่ละชุดเป็น "วัสดุ" ไม่ใช่ "แผนผัง" มันกำหนดเนื้อสัมผัส สี ตัวอักษร และคอมโพเนนต์ แต่ไม่กำหนดว่าแต่ละหน้าต้องมีอะไรบ้าง [3]
ผลคือสองงานที่ใช้ธีมเดียวกันจะออกมาไม่เหมือนกัน
ขั้นที่ 3: สร้างเฉพาะส่วนหัวก่อน
ตรงนี้คือหัวใจของวิธีคิด มันบังคับให้สร้าง hero ให้เสร็จก่อน แล้วเรนเดอร์ออกมาดูด้วยตาเปล่าก่อนที่ส่วนอื่นจะถูกสร้าง [3]
ถ้าส่วนหัวยังไม่ดี ส่วนที่เหลือก็ไม่ต้องเสียเวลา
ขั้นที่ 4: ตรวจด้วย linter ที่รันในเบราว์เซอร์จริง
sloplint.mjs --render จะเปิดหน้าเว็บจริงที่ความกว้างแปดระดับ แล้วตรวจสัญญาณที่อ่านแล้วรู้ว่าเครื่องทำ [3]
จากนั้นมี subagent อีกตัวที่เข้ามาอ่านด้วย "สายตาใหม่" คือบริบทเปล่า ไม่รู้ว่าใครเขียนอะไร เพื่อตรวจรอบสุดท้าย [3]
สัญญาณที่มันจับ
ผมอ่านรายการที่ Hallmark ใช้จับแล้ว คิดว่านี่คือส่วนที่มีค่าที่สุดของรีโป เพราะมันคือรายการอาการของงานออกแบบที่ AI ทำบ่อย [3]
- ป้ายคำสั้น ๆ ที่วางเหนือหัวข้อทุกอัน ทั้งที่ไม่ได้เพิ่มข้อมูลอะไร
- ป้ายตัวพิมพ์ใหญ่ที่เว้นระยะห่างระหว่างตัวอักษร
- คำสีเดียวที่ถูกเน้นในพาดหัว
- หน้าที่มีแต่กรอบว่าง หรือมีแต่รูปถ่ายไม่กี่รูป
- ส่วนหัวที่สูงเกินจอ จนคนอ่านไม่เห็นว่าหน้านี้ขายอะไร
- ช่องสมัครอีเมลที่แปะท้ายทุกหน้า
- ฟอร์มที่ขึ้นว่าขอบคุณ ทั้งที่ไม่มีอะไรถูกส่งไปจริง
README ไม่ได้อ้างงานวิจัยรองรับรายการนี้ นิยามของมันคือ "สัญญาณที่อ่านแล้วรู้ว่าเครื่องทำ" ส่วนเกตบางตัวถูกตั้งเป็นกฎประจำบ้าน เพราะมันคือค่าตั้งต้นที่โมเดลตกไปเอง [3]
ด่านสามชั้นที่ออกแบบมาดี
สิ่งที่ผมชอบที่สุดใน Hallmark คือการแบ่งด่านเป็นสามระดับ ไม่ใช่การบังคับทุกอย่างเท่ากัน [3]
- Floor ห้ามผ่านเด็ดขาด ได้แก่ คอนทราสต์ การเข้าถึงด้วยคีย์บอร์ด การลดการเคลื่อนไหว ข้อมูลที่กุขึ้น และเลย์เอาต์มือถือที่พัง
- Reflex คือพฤติกรรมที่โมเดลมักทำโดยอัตโนมัติ ถ้าทำงานนี้มีเหตุผลจริงสามารถ override ได้ แต่ต้องบันทึกไว้
- Finish คือรายละเอียดงานฝีมือที่ไม่บล็อกการส่งงานเด็ดขาด
การออกแบบแบบนี้ฉลาดเพราะมันแยก "ข้อผิดพลาดที่ยอมรับไม่ได้" ออกจาก "รสนิยม"
ถ้าบังคับทุกอย่างเท่ากัน เครื่องมือจะกลายเป็นคุกที่ไม่มีใครใช้
เรื่องลิขสิทธิ์ที่หลายคนมองข้าม
จุดที่ผมคิดว่าน่าสนใจที่สุดใน README ไม่ใช่เรื่องดีไซน์ แต่เป็นเรื่องภาพถ่าย
Hallmark มีคลังภาพ 755 รูปที่ลิขสิทธิ์แบบเปิด แต่ละรูปมีเงื่อนไขของตัวเอง ทั้ง CC0 สาธารณสมบัติ CC BY และ CC BY-SA และมันเครดิตทุกครั้งที่ใช้ [3]
มันระบุชัดว่า ไม่ใช้ Unsplash, Pexels หรือ Pixabay เพราะเงื่อนไขของเว็บเหล่านี้ห้ามเครื่องมือ AI เลือกภาพ [3]
รายละเอียดนี้บอกอะไรบางอย่างเกี่ยวกับวุฒิภาวะของทีมที่ทำ เพราะมันเป็นจุดที่เครื่องมืออื่นมองข้ามง่ายมาก
โหมดที่ผมคิดว่าใช้งานได้จริงที่สุด
นอกจากสร้างใหม่ Hallmark ยังมีสองโหมดที่ผมคิดว่ามีประโยชน์กับงานจริงมากกว่า [3]
- /hallmark redesign <path> สร้างหน้าใหม่โดยคงเนื้อหาและการเชื่อมต่อเดิมไว้
- /hallmark audit <path> ตรวจเฉย ๆ ไม่แก้อะไร
จุดที่ฉลาดคือก่อนรีดีไซน์ มันจะบันทึกลิงก์ ฟิลด์ ตัวจัดการเหตุการณ์ และหัวข้อทั้งหมดไว้ก่อน แล้วมีคำสั่ง --kept ที่จะทำให้งานล้มเหลวถ้าองค์ประกอบใดหายไป [3]
แปลว่ามันออกแบบมาเพื่อกันความผิดพลาดที่พบบ่อยที่สุดของการให้ AI รื้อโค้ด นั่นคือการทำของเดิมหาย
วิธีติดตั้ง
คำสั่งติดตั้งสั้นมาก และรองรับหลายเครื่องมือ [3]
npx skills add nutlope/hallmark -g
ต้องใช้ Node 18 ขึ้นไป ถ้าต้องการให้ตรวจในเบราว์เซอร์ด้วย ต้องติดตั้ง puppeteer-core และ Chrome เพิ่ม ถ้าไม่มีสองตัวนี้ การตรวจแบบ static ก็ยังทำงานได้ [3]
สำหรับ Claude Code ติดตั้งเป็นปลั๊กอินได้ด้วยคำสั่ง /plugin marketplace add nutlope/hallmark [3]
ข้อจำกัดที่ต้องพูดตรง ๆ
ดาวสี่หมื่นดวงในหกเดือนเป็นสัญญาณความสนใจ ไม่ใช่หลักฐานคุณภาพ
และ Hallmark ไม่ใช่ตัวแรกในตลาดนี้ README เองไล่รายชื่อแรงบันดาลใจไว้เก้ารายการ ทั้ง Impeccable, frontend-design ของ Anthropic, Kami และ taste-skill [3]
แปลว่าปัญหา "AI ทำเว็บซ้ำกัน" เป็นปัญหาที่คนจำนวนมากกำลังแก้ และยังไม่มีใครชนะขาด
ข้อจำกัดอีกอย่างคือมันแก้ได้แค่ชั้นงานออกแบบ ไม่ได้ตัดสินใจแทนคุณว่าควรขายให้ใคร หรือเรื่องเล่าของแบรนด์ควรเป็นอะไร งานส่วนนั้นยังต้องมาจากเจ้าของธุรกิจ
ถ้าเนื้อหาว่าง ดีไซน์ดีแค่ไหนก็ไม่ช่วย
สิ่งที่คนทำเว็บไทยเอาไปใช้ได้เลย
ถึงคุณจะไม่ติดตั้ง Hallmark รายการด้านล่างนี้เอาไปใช้ตรวจงานตัวเองได้ทันที
- เปิดหน้าเว็บที่ AI สร้าง แล้วนับว่ามีกี่หน้าที่ยังมีช่องกรอกอีเมลท้ายหน้า ถ้าเกินครึ่ง แปลว่าคุณกำลังใช้แม่แบบเดียวกันทุกงาน
- ดูว่าส่วนหัวของแต่ละหน้า บอกได้ไหมภายในสามวินาทีว่าหน้านี้ให้อะไร
- ลองปิดรูปภาพทั้งหมด แล้วดูว่าโครงหน้าเว็บยังสื่อสารได้ไหม
- ตรวจว่าฟอร์มทุกอันส่งข้อมูลจริงหรือไม่ เพราะฟอร์มปลอมที่ขึ้นว่าขอบคุณคือความเสียหายต่อแบรนด์มากกว่าดีไซน์ไม่สวย
ถ้าจะสรุปเป็นประโยคเดียว Hallmark ไม่ได้สอน AI ให้สวยขึ้น แต่สอนให้มันตรวจงานตัวเองด้วยกฎที่เขียนไว้ก่อน แล้วยอมให้มนุษย์เป็นคนตัดสินใจเรื่องรสนิยม
คำถามที่ผมคิดว่าควรถามต่อคือ ถ้าเครื่องมืออย่างนี้กลายเป็นมาตรฐาน หน้าเว็บที่ AI สร้างจะกลับมา "เหมือนกัน" อีกครั้งในสไตล์ใหม่หรือไม่
REF
[1] TikTok @aijaidee10 (28 ต.ค. 2026) · สกิลอันทำให้เว็บที่ AI สร้างจะไม่เหมือน AI สร้าง. tiktok.com
[2] GitHub (2026) · Nutlope/hallmark repository metadata. Nutlope/hallmark
[3] Together AI (2026) · Hallmark README. raw.githubusercontent.com
Hallmark — скилл для ИИ-редакторов кода, который делает
дизайн живым Если устал от серых макетов, которые генерирует Claude или Cursor, попробуй Hallmark. Это бесплатный навык для Claude Code, Codex, Cursor и OpenCode. 💻 Внутри 48 готовых стилей, можно...
nutlope/hallmark
Hallmark: A design skill for Claude Code, Codex, Cursor and OpenCode that refuses to look AI-generated (35k stars)
What it does
All text below is quoted directly from the project README.
>Anti-AI-slop design skill for Claude Code, Cursor, and Codex.
New in v2:
- Forty-eight themes. Each is a material (paper, type, colour, surfaces, its own components and texture) with a picture of a finished page, and the build lays out its own page in it.
- Built from the job. A booking page books, a shop sells, a newsletter subscribes: the action sits where the category puts it, and the page ends on it.
- Custom. Ask for a custom page and Hallmark designs from your prompt alone, under the same rules and checks.
- Your real product. Point it at a URL, a dev server or an app and it captures the screenshots itself.
- Real photographs. 755 openly licensed photos, picked per subject and credited on the page.
- Redesign and audit. /hallmark redesign <path> rebuilds a page and keeps its content and wiring; /hallmark audit <path> only reports.
>npx skills add nutlope/hallmark -g
Repository
nutlope/hallmark
Repository stats
|Metric|Value|
|:-|:-|
|Stars|35,855|
|Forks|1.9k|
|Last release|None|
|Languages|CSS 43.3%, HTML 37.4%, JavaScript 18.1%|
|Contributors|8|
|AI contributor accounts (Claude / Codex / Cursor / Copilot)|@claude (76 commits)|
|AI co-authored commits|Claude: 76|
Main contributor
|Field|Value|
|:-|:-|
|Name|Youssef|
|GitHub|@Luffixos|
|Commits to this repo|279 (top contributor)|
|Bio|Product Designer @ Together AI|
|Company / Location|Together AI / Morocco|
|X / Twitter|@youssefuiux|
|Followers|124|
──────────────────────────────
📌 How many great GitHub repos have you discovered and completely forgotten about?
Don't let another useful tool disappear into your Reddit feed. Get the community's best repos, organized by category, plus key takeaways from real developer discussions, delivered to your inbox twice a week.
📬 Never lose track of great repos again. Subscribe free.
601 points · 19 comments
When Your Settings Modal Looks Perfect But Traps Focus Behind Itself
When Your Settings Modal Looks Perfect But Traps Focus Behind Itself
You ship a settings panel. Design sign-off was clean. Two weeks later, a customer using VoiceOver reports they cannot rename their workspace because focus jumps to the page footer mid-dialog. You add tabindex="-1" to the overlay. Another customer on Windows Narrator complains the Escape key closes the browser tab instead of the modal. You patch keyboard listeners. Six months in, you maintain 140 lines of focus management that breaks whenever someone nests a dropdown inside the dialog.
The expensive defect was not the border radius. It was treating modal semantics as a styling problem.
I evaluated Nutlope/hallmark as design guidance, not as the owner of interaction contracts. Its anti-slop focus addresses visual sameness in AI-generated interfaces. The integration boundary matters: let design direction shape hierarchy and composition; application code must enforce semantics, state transitions, and motion constraints.
This is an architectural adoption pattern based on that stated scope, not a claim that I audited the repository's implementation.
The boundary: design intent outside, interaction guarantees inside
For a reusable rename dialog, I separate three responsibilities.
The application owns the saved name and persistence. The component owns the temporary draft and submission boundary. Radix Dialog owns modal behavior: focus containment, Escape dismissal, accessible labeling, and focus restoration under its normal lifecycle.
Tailwind handles visible states. A small CSS layer handles responsive action layout and entrance motion.
That separation prevents a common production failure: a visually customized modal gradually replacing accessibility behavior with document listeners and hand-maintained lists of focusable elements. Those lists break when validation inserts another control, a button becomes disabled, or nested content changes.
The implementation below assumes a working React/TypeScript application with Tailwind CSS v4. Install @radix-ui/react-dialog; for Tailwind's Vite integration, install tailwindcss and @tailwindcss/vite, then register tailwindcss() alongside the React plugin in the existing Vite configuration.
A dialog with a narrow contract
This component deliberately accepts a synchronous onSave. It commits a valid draft and closes. Network persistence needs a separate pending-and-error contract; pretending every save completes instantly is another tutorial shortcut that leaks into production.
import { useId, useState } from "react";
import * as Dialog from "@radix-ui/react-dialog";
type RenameDialogProps = {
name: string;
onSave: (name: string) => void;
};
const button =
"rounded-md px-4 py-2 text-sm font-medium " +
"focus-visible:outline-2 focus-visible:outline-offset-2 " +
"focus-visible:outline-indigo-600";
export function RenameDialog({ name, onSave }: RenameDialogProps) {
const [open, setOpen] = useState(false);
const [draft, setDraft] = useState(name);
const fieldId = useId();
return (
<Dialog.Root
open={open}
onOpenChange={(next) => {
if (next) setDraft(name);
setOpen(next);
}}
>
<Dialog.Trigger asChild>
<button className={`${button} border border-slate-300`}>
Rename workspace
</button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 z-40 bg-slate-950/50" />
<Dialog.Content
className="rename-dialog fixed top-1/2 left-1/2 z-50
max-h-[calc(100dvh_-_2rem)] w-[calc(100%_-_2rem)]
max-w-lg -translate-x-1/2 -translate-y-1/2
overflow-y-auto rounded-xl border border-slate-200
bg-white p-6 text-slate-950 shadow-xl"
>
<Dialog.Title className="text-xl font-semibold tracking-tight">
Rename workspace
</Dialog.Title>
<Dialog.Description className="mt-2 text-sm text-slate-600">
Choose a name your teammates will recognize.
</Dialog.Description>
<form
className="mt-6"
onSubmit={(event) => {
event.preventDefault();
const value = draft.trim();
if (!value) return;
onSave(value);
setOpen(false);
}}
>
<label htmlFor={fieldId} className="text-sm font-medium">
Workspace name
</label>
<input
id={fieldId}
value={draft}
onChange={(event) => setDraft(event.target.value)}
required
maxLength={80}
autoComplete="off"
className="mt-2 block w-full rounded-md border
border-slate-400 px-3 py-2
focus-visible:outline-2
focus-visible:outline-indigo-600"
/>
<div className="rename-actions mt-6">
<Dialog.Close asChild>
<button
type="button"
className={`${button} border border-slate-300`}
>
Cancel
</button>
</Dialog.Close>
<button
type="submit"
disabled={!draft.trim()}
className={`${button} bg-indigo-700 text-white
disabled:cursor-not-allowed disabled:opacity-50`}
>
Save name
</button>
</div>
</form>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}
Radix supplies role="dialog", modal semantics, and the title/description associations. Adding duplicate ARIA attributes manually would create another source of truth. The input keeps an explicit label because dialog descriptions do not replace field labels.
Motion should not become a layout engine
A production failure pattern worth recognizing is a resize animation that reads scrollHeight, writes height, then measures again on every frame. Interleaving those reads and writes can force repeated layout work. Adding more animation frames does not fix the dependency cycle.
Here is the complete global CSS configuration and micro-interaction layer:
@import "tailwindcss";
.rename-dialog {
container-type: inline-size;
}
.rename-dialog[data-state="open"] {
animation: dialog-enter 140ms ease-out;
}
.rename-actions {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
@container (min-width: 24rem) {
.rename-actions {
flex-direction: row;
justify-content: flex-end;
}
}
@keyframes dialog-enter {
from {
opacity: 0;
scale: 0.98;
}
to {
opacity: 1;
scale: 1;
}
}
The animation runs once when data-state="open" appears. No JavaScript intervention. Container queries handle button layout without breakpoints or ResizeObserver polling.
When the contract changes
If the save operation becomes async, this component's contract must expand. The natural boundary is to lift draft and pending state out, then pass onSave: (name: string) => Promise<void> down. The component can then disable both buttons and the input while pending is true, show inline error feedback, and only close on successful resolution.
That separation keeps Radix Dialog responsible for focus and dismissal semantics, but lets the application control when closure is permitted. Disabling the close button during async work is a clear signal; silently ignoring Escape creates invisible modal behavior.
The integration layer that matters
A design system that delivers visual consistency does valuable work. The failure is assuming it also delivers interaction contracts. Focus traps, dismissal behavior, accessible labeling, and state coordination are not styling concerns.
Radix Dialog provides those contracts. Tailwind provides utility composition. The boundary between them is load-bearing. Cross it intentionally or maintain the duplication yourself.
1 reaction · 1 comment
Trending repository of the day 📈
hallmark by @nutlope
Anti-AI-slop design skill for Claude Code, Cursor, and Codex.
Last 24h: 2,859 ⭐
Total: 37,891 ⭐️
Nutlope/hallmark
20 likes · 2 reposts · 2,068 views
Mentions
Vibe designers, thank me later. Nutlope/hallmark
سایتهایی که با هوش مصنوعی میسازی چرا همهشون شبیه همن؟ - این اسکیل ۴۱ هزار ستاره داره و ۵۰ تم میده - الگوهای تکراری رو قبل از انتشار میگیره سایت تو هم این نشونهها رو داره؟ سایتش اینجاست: nutlope/hallmark
Hallmark checks AI-built pages for generic design habits. What would you test it against? I'm Obi, the builder of RepoQuarry. This is our one-minute Hallmark overview, presented by Sky, whose image and voice are AI-generated. Hallmark is a design skill made by Together AI, hosted at Nutlope/hallmark. The README describes a choice of three themes from fifty, layouts shaped around the page's actual purpose, and a browser checker called sloplint running at eight widths. It also describes credited, openly licensed photos and asking for real product facts instead of inventing them. That is the documented workflow, not our test result. We've read the docs but haven't installed or run it. The skill is MIT licensed; you still need a coding agent and may pay for its plan or API usage. Browser checks need Chrome and puppeteer-core. Stars indicate interest, not a quality rating; the video's counts are dated 1 November. Creator/source: Nutlope/hallmark Official demo: usehallmark.com RepoQuarry breakdown and requirements: repoquarry.dev If you've tried design skills like this, what would be a fair test: an existing page redesign, an accessible booking flow, or the same brief across several agents? reddit.com
Taste can't be linted. The tells can. --- title: "Taste can't be linted. The tells can." published: true published_at: 2026-10-30 11:00 -0700 tags: webdev, ai, opensource, discuss cover_image: beehiiv-images-production.s3.amazonaws.com --- My product's homepage has six top-level headings. Every one has a small pill or a line of capitals above it, and every one ends on a word set in italic serif. I didn't notice until I pointed a design lint's rules at the page. Two of the pills say phrases that appear word for word in the lint's source code. The lint ships inside Hallmark, and it changed how I think about the "AI slop" complaint. You can't write a test for taste. You can write one for the tells. A design skill with a script behind it Hallmark is an MIT-licensed skill for Claude Code, Codex, Cursor and OpenCode, made by Hassan El Mghari (Nutlope) at Together AI. Version 2 (2.0.0 in its package.json) was merged on October 22. It was #1 on GitHub trending on Tuesday with 2,830 stars that day, and the GitHub API showed 39,048 stars when I checked that evening. Most design skills are a long prompt. This one is a prompt plus machinery. SKILL.md opens with a 16-rule Floor no build may break, then a flow: read the project, ask once for real material, deal three themes, build and review the hero alone, then sweep the page. There are 50 themes (I counted 50 files and 50 preview images). The rules live in references/gates.md, and the checker is scripts/sloplint.mjs: 4,422 lines, zero dependencies, Node 18 and up. Install is one line: npx skills add nutlope/hallmark -g The tells, written down as rules gates.md is the file worth reading. It lists 90 numbered gates, each with a tier and a class. Floor gates never ship. Reflex gates are a model's defaults, and a build may waive one in a CSS comment with a real reason. Class M means the static script can settle it from CSS and markup; R needs a real browser; J is judgment at review time. I counted 45 M gates and 9 judged only. The named tells read like things most of us have shipped: the eyebrow (a short line announcing the heading under it), the tracked-caps label, one coloured word in a headline, middle dots between meta items, a form that says "Thanks" while sending nothing. Four are "house rules" (the eyebrow, tracked caps, an 80-words-per-screen budget, template punctuation), which sit in the Floor with no waiver. What sold me is how literal the script gets. This is how it decides a gradient is purple-to-blue: const purple = stops.some((h) => hueIn(h, 265, 330)); const blue = stops.some((h) => hueIn(h, 200, 264)); // ... if (purple && blue) return 'purple-to-blue'; Each stop is converted to OKLCH first, and only counts with chroma above 0.04, so a grey wash passes. transition: all is one regex. A tracked-caps label is uppercase, small caps or letter-spacing past 0.03em on anything named like a label (badge, meta, nav, caption and about twenty more) or set at 15px or under. An eyebrow is a short line before a heading with a class like kicker or badge, two style signals, or one of a fixed list of announcing phrases. It reads Tailwind class strings in .jsx, .tsx, .vue, .svelte and .astro files too, including cn() and clsx() calls. I ran five of the rules on my own homepage I didn't run sloplint. It's downloaded code, and I don't execute that for a post. I read the functions, ported five checks to about 100 lines of Python, and ran them on the HTML and CSS of somiibo.com, my product's homepage. The CSS is one 217 KB bundle: Bootstrap 5.3.6, then the site's own layer. My scripts print one line per finding; here is the tally: transition: all 16 rules (15 site layer, 1 inline) animated height/width 2 (Bootstrap's own .collapsing) purple-to-blue gradient 7 rules, 2 in use (hero, pills) tracked capitals 0 middle-dot strings 0 eyebrows 6 above 6 headings accented word 6 of 6 headings focus styles present (passes) overflow-x: clip missing on html and body The headings stung. Each h1 and h2 wraps its last word or two in <span class="text-accent">, an italic serif: "Grow your social media on autopilot", "Unlock your growth potential". Each also has an eyebrow: capitals over the h1, a pill over every h2. Two pills say "How it works" and "Get started", both on the lint's list. The gradient is less clear-cut. The hero uses an eight-stop rainbow with #a166ab (hue 322 by my conversion) and #5073b8 (263) in it, so the rule calls it purple-to-blue, though no person would. The textbook case, #5b47fb to #00d4ff, sits in the same stylesheet, unused on this page. The static tier reads rules, not usage. The passes were real: no positive letter-spacing anywhere, no text joining items with two middle dots, and focus styles exist. I tried ianwiedenman.com too. Above my name sits "Hello, I'm" in a <p class="text-uppercase tracking-widest">, an eyebrow asking for tracked caps. But tracking-widest is a Tailwind class on a Bootstrap site, and neither of its stylesheets defines it, so the browser draws plain capitals. The glow behind it is three radial gradients whose custom properties are named --grad-purple-x, --grad-cyan-x and --grad-pink-x. Why a lint beats a paragraph of taste Here's my claim. "Make it look premium" in a prompt is a wish. A model can agree with it and has no way to check its output against it. "No stop between hue 265 and 330 beside one between 200 and 264" is a test. It fails a build, names a line, and doesn't get tired. There's evidence this matters. In September a user, ktlesr, posted a measurement in issue #74 on an earlier version: four landing-page briefs built with and without the skill, scored by pattern checks. Pure black or white appeared on 40 of 40 pages without it and 14 of 28 with it. transition: all didn't drop (14 of 40 against 16 of 28). Their reading: that rule lived in a reference file the model never opened. Version 2 reads like the answer. transition: all is now rule 2 of the Floor, in the file that always loads, and rule 16 tells the agent to run sloplint, when Node is available, and fix every FAIL before handing back. A rule in prose can be skipped. A script with an exit code can't, as long as something runs it. Where a lint stops A lint on tells is a floor, not a design. Strip the eyebrows and italic words from my homepage and it avoids a dozen mistakes, but it still has no idea of its own. Builds pushed away from the same defaults can also converge on a new shared look. In a July HN thread, mstkllah said design skills like this all end up in the same place unless you are very explicit. Hallmark's answer sits outside the lint: themes dealt from fifty, a log of past builds the deal avoids, and a reviewer subagent that reads the page cold. That part is judgment, and I didn't test it. Some rules are opinions. "Never an eyebrow" and "never tracked caps" are house rules, so no waiver. A magazine that sets section labels in spaced small caps on purpose is breaking the Floor. One rough edge in the source: --tier isn't validated. Pass --tier Floor with a capital F and the filter matches nothing, so the run prints clean and exits 0. PR #93 reported it and was closed unmerged; the commit I read (6033bab) still does it. My own checks were static only. The fold and anything measured on the rendered page need the render tier, which needs Chrome and puppeteer-core. Try it on a page you already have After the install, /hallmark audit ./index.html reports without redesigning anything. From a clone, the bare lint is node skills/hallmark/scripts/sloplint.mjs index.html. I haven't run either; I read the source and reproduced a few checks by hand. One detail I liked: the photo library is 755 openly licensed pictures on Wikimedia Commons, credited on the page. The README says it skips Unsplash, Pexels and Pixabay because their terms bar AI tools from picking their images. Which of these tells is on your own homepage right now, and is it there on purpose?
Bygga offers animated, step-by-step 3D guides for assembling IKEA furniture, using AI to scan and interpret paper manuals. The tool generates interactive instructions for over 1,171 products, allowing users to navigate each assembly process seamlessly. Nutlope/bygga
Hallmark คืออะไร? สกิลที่บังคับให้ AI ทำเว็บไม่ให้ดูเป็น AI โดย Nokka (นก-กา) | ตรวจข้อมูล 29 ต.ค. 2026 บทความนี้เขียนโดย AI (deepseek-v4.1-flash · ผู้ให้บริการโมเดล: ollama-cloud) ผ่าน Hermes Agent ภายใต้การควบคุมและตรวจสอบคุณภาพโดยมนุษย์ - Nokka (นก-กา) !ภาพประกอบ: หน้าเว็บหลายหน้าซ้อนกันโดยมีไม้บรรทัดและตารางวัดทาบอยู่ด้านบน ถ้าคุณเคยให้ AI สร้างหน้าเว็บสักสิบหน้า คุณคงสังเกตเห็นอะไรบางอย่าง มันดูคล้ายกันไปหมด ไล่ตั้งแต่หัวข้อตัวใหญ่ที่จัดกลาง ป้ายตัวเล็กตัวพิมพ์ใหญ่ห่างกันเหนือหัวข้อ ปุ่มมุมโค้งที่ไล่สีสวย แล้วปิดท้ายด้วยช่องกรอกอีเมล ผมคิดว่าความเหมือนนี้ไม่ใช่เรื่องบังเอิญ มันออกมาจากที่เดียวกัน คือรูปแบบที่โมเดลเรียนจากหน้าเว็บจำนวนมหาศาล ผมเจอเครื่องมือที่สร้างมาเพื่อสู้กับเรื่องนี้โดยเฉพาะจากคลิปของ @aijaidee10 [1] มันชื่อ Hallmark Hallmark คืออะไร Hallmark เป็นสกิลสำหรับ AI coding agent ใช้ได้กับ Claude Code, Codex, Cursor และ OpenCode [2] จุดยืนของมันเขียนไว้ชัดในรีโป คือ "ปฏิเสธที่จะดูเหมือนงานที่ AI สร้าง" และมันทำงานโดยการบังคับกฎ แล้วปล่อยให้โมเดลทำงานต่อ [3] ตัวเลข ณ วันที่ผมตรวจคือ 40,998 ดาว 2,126 forks สัญญาอนุญาต MIT สร้างเมื่อ 27 เม.ย. 2026 และอัปเดตล่าสุด 28 ต.ค. 2026 [2] รีโปนี้พัฒนาโดยทีม Together AI ตามที่ระบุใน README [3] กลไกที่ทำให้มันต่างจาก prompt สวย ๆ สกิลออกแบบเว็บทั่วไปมักเป็นไฟล์ Markdown ที่บอกว่า "จงออกแบบให้สวย ทันสมัย อย่าใช้สีฉูดฉาด" Hallmark ไม่ได้หยุดที่คำแนะนำ แต่มีด่านตรวจที่รันโค้ดจริง ขั้นที่ 1: อ่านโปรเจกต์ก่อนออกแบบ ก่อนเริ่ม มันจะอ่านโปรเจกต์เพื่อดูฟอนต์ ชุดสี เฟรมเวิร์ก และไฟล์ design.md ที่ถูกล็อกไว้ แล้วถามหาวัสดุจริงอย่างรูปถ่าย ภาพหน้าจอ และตัวเลขจริง [3] จุดนี้สำคัญเพราะปัญหาหนึ่งของงาน AI คือการแต่งข้อมูลขึ้นมา ถ้าไม่มีข้อมูลจริง มันจะไม่ยอมแต่ง ขั้นที่ 2: แจกธีมสามจากห้าสิบ คำสั่ง theme.mjs deal จะเลือกธีมสามชุดที่เข้ากับโจทย์ และกันไม่ให้ซ้ำกับสามงานล่าสุดที่บันทึกไว้ใน log [3] ธีมแต่ละชุดเป็น "วัสดุ" ไม่ใช่ "แผนผัง" มันกำหนดเนื้อสัมผัส สี ตัวอักษร และคอมโพเนนต์ แต่ไม่กำหนดว่าแต่ละหน้าต้องมีอะไรบ้าง [3] ผลคือสองงานที่ใช้ธีมเดียวกันจะออกมาไม่เหมือนกัน ขั้นที่ 3: สร้างเฉพาะส่วนหัวก่อน ตรงนี้คือหัวใจของวิธีคิด มันบังคับให้สร้าง hero ให้เสร็จก่อน แล้วเรนเดอร์ออกมาดูด้วยตาเปล่าก่อนที่ส่วนอื่นจะถูกสร้าง [3] ถ้าส่วนหัวยังไม่ดี ส่วนที่เหลือก็ไม่ต้องเสียเวลา ขั้นที่ 4: ตรวจด้วย linter ที่รันในเบราว์เซอร์จริง sloplint.mjs --render จะเปิดหน้าเว็บจริงที่ความกว้างแปดระดับ แล้วตรวจสัญญาณที่อ่านแล้วรู้ว่าเครื่องทำ [3] จากนั้นมี subagent อีกตัวที่เข้ามาอ่านด้วย "สายตาใหม่" คือบริบทเปล่า ไม่รู้ว่าใครเขียนอะไร เพื่อตรวจรอบสุดท้าย [3] สัญญาณที่มันจับ ผมอ่านรายการที่ Hallmark ใช้จับแล้ว คิดว่านี่คือส่วนที่มีค่าที่สุดของรีโป เพราะมันคือรายการอาการของงานออกแบบที่ AI ทำบ่อย [3] - ป้ายคำสั้น ๆ ที่วางเหนือหัวข้อทุกอัน ทั้งที่ไม่ได้เพิ่มข้อมูลอะไร - ป้ายตัวพิมพ์ใหญ่ที่เว้นระยะห่างระหว่างตัวอักษร - คำสีเดียวที่ถูกเน้นในพาดหัว - หน้าที่มีแต่กรอบว่าง หรือมีแต่รูปถ่ายไม่กี่รูป - ส่วนหัวที่สูงเกินจอ จนคนอ่านไม่เห็นว่าหน้านี้ขายอะไร - ช่องสมัครอีเมลที่แปะท้ายทุกหน้า - ฟอร์มที่ขึ้นว่าขอบคุณ ทั้งที่ไม่มีอะไรถูกส่งไปจริง README ไม่ได้อ้างงานวิจัยรองรับรายการนี้ นิยามของมันคือ "สัญญาณที่อ่านแล้วรู้ว่าเครื่องทำ" ส่วนเกตบางตัวถูกตั้งเป็นกฎประจำบ้าน เพราะมันคือค่าตั้งต้นที่โมเดลตกไปเอง [3] ด่านสามชั้นที่ออกแบบมาดี สิ่งที่ผมชอบที่สุดใน Hallmark คือการแบ่งด่านเป็นสามระดับ ไม่ใช่การบังคับทุกอย่างเท่ากัน [3] - Floor ห้ามผ่านเด็ดขาด ได้แก่ คอนทราสต์ การเข้าถึงด้วยคีย์บอร์ด การลดการเคลื่อนไหว ข้อมูลที่กุขึ้น และเลย์เอาต์มือถือที่พัง - Reflex คือพฤติกรรมที่โมเดลมักทำโดยอัตโนมัติ ถ้าทำงานนี้มีเหตุผลจริงสามารถ override ได้ แต่ต้องบันทึกไว้ - Finish คือรายละเอียดงานฝีมือที่ไม่บล็อกการส่งงานเด็ดขาด การออกแบบแบบนี้ฉลาดเพราะมันแยก "ข้อผิดพลาดที่ยอมรับไม่ได้" ออกจาก "รสนิยม" ถ้าบังคับทุกอย่างเท่ากัน เครื่องมือจะกลายเป็นคุกที่ไม่มีใครใช้ เรื่องลิขสิทธิ์ที่หลายคนมองข้าม จุดที่ผมคิดว่าน่าสนใจที่สุดใน README ไม่ใช่เรื่องดีไซน์ แต่เป็นเรื่องภาพถ่าย Hallmark มีคลังภาพ 755 รูปที่ลิขสิทธิ์แบบเปิด แต่ละรูปมีเงื่อนไขของตัวเอง ทั้ง CC0 สาธารณสมบัติ CC BY และ CC BY-SA และมันเครดิตทุกครั้งที่ใช้ [3] มันระบุชัดว่า ไม่ใช้ Unsplash, Pexels หรือ Pixabay เพราะเงื่อนไขของเว็บเหล่านี้ห้ามเครื่องมือ AI เลือกภาพ [3] รายละเอียดนี้บอกอะไรบางอย่างเกี่ยวกับวุฒิภาวะของทีมที่ทำ เพราะมันเป็นจุดที่เครื่องมืออื่นมองข้ามง่ายมาก โหมดที่ผมคิดว่าใช้งานได้จริงที่สุด นอกจากสร้างใหม่ Hallmark ยังมีสองโหมดที่ผมคิดว่ามีประโยชน์กับงานจริงมากกว่า [3] - /hallmark redesign <path> สร้างหน้าใหม่โดยคงเนื้อหาและการเชื่อมต่อเดิมไว้ - /hallmark audit <path> ตรวจเฉย ๆ ไม่แก้อะไร จุดที่ฉลาดคือก่อนรีดีไซน์ มันจะบันทึกลิงก์ ฟิลด์ ตัวจัดการเหตุการณ์ และหัวข้อทั้งหมดไว้ก่อน แล้วมีคำสั่ง --kept ที่จะทำให้งานล้มเหลวถ้าองค์ประกอบใดหายไป [3] แปลว่ามันออกแบบมาเพื่อกันความผิดพลาดที่พบบ่อยที่สุดของการให้ AI รื้อโค้ด นั่นคือการทำของเดิมหาย วิธีติดตั้ง คำสั่งติดตั้งสั้นมาก และรองรับหลายเครื่องมือ [3] npx skills add nutlope/hallmark -g ต้องใช้ Node 18 ขึ้นไป ถ้าต้องการให้ตรวจในเบราว์เซอร์ด้วย ต้องติดตั้ง puppeteer-core และ Chrome เพิ่ม ถ้าไม่มีสองตัวนี้ การตรวจแบบ static ก็ยังทำงานได้ [3] สำหรับ Claude Code ติดตั้งเป็นปลั๊กอินได้ด้วยคำสั่ง /plugin marketplace add nutlope/hallmark [3] ข้อจำกัดที่ต้องพูดตรง ๆ ดาวสี่หมื่นดวงในหกเดือนเป็นสัญญาณความสนใจ ไม่ใช่หลักฐานคุณภาพ และ Hallmark ไม่ใช่ตัวแรกในตลาดนี้ README เองไล่รายชื่อแรงบันดาลใจไว้เก้ารายการ ทั้ง Impeccable, frontend-design ของ Anthropic, Kami และ taste-skill [3] แปลว่าปัญหา "AI ทำเว็บซ้ำกัน" เป็นปัญหาที่คนจำนวนมากกำลังแก้ และยังไม่มีใครชนะขาด ข้อจำกัดอีกอย่างคือมันแก้ได้แค่ชั้นงานออกแบบ ไม่ได้ตัดสินใจแทนคุณว่าควรขายให้ใคร หรือเรื่องเล่าของแบรนด์ควรเป็นอะไร งานส่วนนั้นยังต้องมาจากเจ้าของธุรกิจ ถ้าเนื้อหาว่าง ดีไซน์ดีแค่ไหนก็ไม่ช่วย สิ่งที่คนทำเว็บไทยเอาไปใช้ได้เลย ถึงคุณจะไม่ติดตั้ง Hallmark รายการด้านล่างนี้เอาไปใช้ตรวจงานตัวเองได้ทันที - เปิดหน้าเว็บที่ AI สร้าง แล้วนับว่ามีกี่หน้าที่ยังมีช่องกรอกอีเมลท้ายหน้า ถ้าเกินครึ่ง แปลว่าคุณกำลังใช้แม่แบบเดียวกันทุกงาน - ดูว่าส่วนหัวของแต่ละหน้า บอกได้ไหมภายในสามวินาทีว่าหน้านี้ให้อะไร - ลองปิดรูปภาพทั้งหมด แล้วดูว่าโครงหน้าเว็บยังสื่อสารได้ไหม - ตรวจว่าฟอร์มทุกอันส่งข้อมูลจริงหรือไม่ เพราะฟอร์มปลอมที่ขึ้นว่าขอบคุณคือความเสียหายต่อแบรนด์มากกว่าดีไซน์ไม่สวย ถ้าจะสรุปเป็นประโยคเดียว Hallmark ไม่ได้สอน AI ให้สวยขึ้น แต่สอนให้มันตรวจงานตัวเองด้วยกฎที่เขียนไว้ก่อน แล้วยอมให้มนุษย์เป็นคนตัดสินใจเรื่องรสนิยม คำถามที่ผมคิดว่าควรถามต่อคือ ถ้าเครื่องมืออย่างนี้กลายเป็นมาตรฐาน หน้าเว็บที่ AI สร้างจะกลับมา "เหมือนกัน" อีกครั้งในสไตล์ใหม่หรือไม่ REF [1] TikTok @aijaidee10 (28 ต.ค. 2026) · สกิลอันทำให้เว็บที่ AI สร้างจะไม่เหมือน AI สร้าง. tiktok.com [2] GitHub (2026) · Nutlope/hallmark repository metadata. Nutlope/hallmark [3] Together AI (2026) · Hallmark README. raw.githubusercontent.com
Hallmark — скилл для ИИ-редакторов кода, который делает дизайн живым Если устал от серых макетов, которые генерирует Claude или Cursor, попробуй Hallmark. Это бесплатный навык для Claude Code, Codex, Cursor и OpenCode. 💻 Внутри 48 готовых стилей, можно... nutlope/hallmark
Hallmark: A design skill for Claude Code, Codex, Cursor and OpenCode that refuses to look AI-generated (35k stars) What it does All text below is quoted directly from the project README. >Anti-AI-slop design skill for Claude Code, Cursor, and Codex. New in v2: - Forty-eight themes. Each is a material (paper, type, colour, surfaces, its own components and texture) with a picture of a finished page, and the build lays out its own page in it. - Built from the job. A booking page books, a shop sells, a newsletter subscribes: the action sits where the category puts it, and the page ends on it. - Custom. Ask for a custom page and Hallmark designs from your prompt alone, under the same rules and checks. - Your real product. Point it at a URL, a dev server or an app and it captures the screenshots itself. - Real photographs. 755 openly licensed photos, picked per subject and credited on the page. - Redesign and audit. /hallmark redesign <path> rebuilds a page and keeps its content and wiring; /hallmark audit <path> only reports. >npx skills add nutlope/hallmark -g Repository nutlope/hallmark Repository stats |Metric|Value| |:-|:-| |Stars|35,855| |Forks|1.9k| |Last release|None| |Languages|CSS 43.3%, HTML 37.4%, JavaScript 18.1%| |Contributors|8| |AI contributor accounts (Claude / Codex / Cursor / Copilot)|@claude (76 commits)| |AI co-authored commits|Claude: 76| Main contributor |Field|Value| |:-|:-| |Name|Youssef| |GitHub|@Luffixos| |Commits to this repo|279 (top contributor)| |Bio|Product Designer @ Together AI| |Company / Location|Together AI / Morocco| |X / Twitter|@youssefuiux| |Followers|124| ────────────────────────────── 📌 How many great GitHub repos have you discovered and completely forgotten about? Don't let another useful tool disappear into your Reddit feed. Get the community's best repos, organized by category, plus key takeaways from real developer discussions, delivered to your inbox twice a week. 📬 Never lose track of great repos again. Subscribe free.
When Your Settings Modal Looks Perfect But Traps Focus Behind Itself When Your Settings Modal Looks Perfect But Traps Focus Behind Itself You ship a settings panel. Design sign-off was clean. Two weeks later, a customer using VoiceOver reports they cannot rename their workspace because focus jumps to the page footer mid-dialog. You add tabindex="-1" to the overlay. Another customer on Windows Narrator complains the Escape key closes the browser tab instead of the modal. You patch keyboard listeners. Six months in, you maintain 140 lines of focus management that breaks whenever someone nests a dropdown inside the dialog. The expensive defect was not the border radius. It was treating modal semantics as a styling problem. I evaluated Nutlope/hallmark as design guidance, not as the owner of interaction contracts. Its anti-slop focus addresses visual sameness in AI-generated interfaces. The integration boundary matters: let design direction shape hierarchy and composition; application code must enforce semantics, state transitions, and motion constraints. This is an architectural adoption pattern based on that stated scope, not a claim that I audited the repository's implementation. The boundary: design intent outside, interaction guarantees inside For a reusable rename dialog, I separate three responsibilities. The application owns the saved name and persistence. The component owns the temporary draft and submission boundary. Radix Dialog owns modal behavior: focus containment, Escape dismissal, accessible labeling, and focus restoration under its normal lifecycle. Tailwind handles visible states. A small CSS layer handles responsive action layout and entrance motion. That separation prevents a common production failure: a visually customized modal gradually replacing accessibility behavior with document listeners and hand-maintained lists of focusable elements. Those lists break when validation inserts another control, a button becomes disabled, or nested content changes. The implementation below assumes a working React/TypeScript application with Tailwind CSS v4. Install @radix-ui/react-dialog; for Tailwind's Vite integration, install tailwindcss and @tailwindcss/vite, then register tailwindcss() alongside the React plugin in the existing Vite configuration. A dialog with a narrow contract This component deliberately accepts a synchronous onSave. It commits a valid draft and closes. Network persistence needs a separate pending-and-error contract; pretending every save completes instantly is another tutorial shortcut that leaks into production. import { useId, useState } from "react"; import * as Dialog from "@radix-ui/react-dialog"; type RenameDialogProps = { name: string; onSave: (name: string) => void; }; const button = "rounded-md px-4 py-2 text-sm font-medium " + "focus-visible:outline-2 focus-visible:outline-offset-2 " + "focus-visible:outline-indigo-600"; export function RenameDialog({ name, onSave }: RenameDialogProps) { const [open, setOpen] = useState(false); const [draft, setDraft] = useState(name); const fieldId = useId(); return ( <Dialog.Root open={open} onOpenChange={(next) => { if (next) setDraft(name); setOpen(next); }} > <Dialog.Trigger asChild> <button className={`${button} border border-slate-300`}> Rename workspace </button> </Dialog.Trigger> <Dialog.Portal> <Dialog.Overlay className="fixed inset-0 z-40 bg-slate-950/50" /> <Dialog.Content className="rename-dialog fixed top-1/2 left-1/2 z-50 max-h-[calc(100dvh_-_2rem)] w-[calc(100%_-_2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-xl border border-slate-200 bg-white p-6 text-slate-950 shadow-xl" > <Dialog.Title className="text-xl font-semibold tracking-tight"> Rename workspace </Dialog.Title> <Dialog.Description className="mt-2 text-sm text-slate-600"> Choose a name your teammates will recognize. </Dialog.Description> <form className="mt-6" onSubmit={(event) => { event.preventDefault(); const value = draft.trim(); if (!value) return; onSave(value); setOpen(false); }} > <label htmlFor={fieldId} className="text-sm font-medium"> Workspace name </label> <input id={fieldId} value={draft} onChange={(event) => setDraft(event.target.value)} required maxLength={80} autoComplete="off" className="mt-2 block w-full rounded-md border border-slate-400 px-3 py-2 focus-visible:outline-2 focus-visible:outline-indigo-600" /> <div className="rename-actions mt-6"> <Dialog.Close asChild> <button type="button" className={`${button} border border-slate-300`} > Cancel </button> </Dialog.Close> <button type="submit" disabled={!draft.trim()} className={`${button} bg-indigo-700 text-white disabled:cursor-not-allowed disabled:opacity-50`} > Save name </button> </div> </form> </Dialog.Content> </Dialog.Portal> </Dialog.Root> ); } Radix supplies role="dialog", modal semantics, and the title/description associations. Adding duplicate ARIA attributes manually would create another source of truth. The input keeps an explicit label because dialog descriptions do not replace field labels. Motion should not become a layout engine A production failure pattern worth recognizing is a resize animation that reads scrollHeight, writes height, then measures again on every frame. Interleaving those reads and writes can force repeated layout work. Adding more animation frames does not fix the dependency cycle. Here is the complete global CSS configuration and micro-interaction layer: @import "tailwindcss"; .rename-dialog { container-type: inline-size; } .rename-dialog[data-state="open"] { animation: dialog-enter 140ms ease-out; } .rename-actions { display: flex; flex-direction: column; gap: 0.75rem; } @container (min-width: 24rem) { .rename-actions { flex-direction: row; justify-content: flex-end; } } @keyframes dialog-enter { from { opacity: 0; scale: 0.98; } to { opacity: 1; scale: 1; } } The animation runs once when data-state="open" appears. No JavaScript intervention. Container queries handle button layout without breakpoints or ResizeObserver polling. When the contract changes If the save operation becomes async, this component's contract must expand. The natural boundary is to lift draft and pending state out, then pass onSave: (name: string) => Promise<void> down. The component can then disable both buttons and the input while pending is true, show inline error feedback, and only close on successful resolution. That separation keeps Radix Dialog responsible for focus and dismissal semantics, but lets the application control when closure is permitted. Disabling the close button during async work is a clear signal; silently ignoring Escape creates invisible modal behavior. The integration layer that matters A design system that delivers visual consistency does valuable work. The failure is assuming it also delivers interaction contracts. Focus traps, dismissal behavior, accessible labeling, and state coordination are not styling concerns. Radix Dialog provides those contracts. Tailwind provides utility composition. The boundary between them is load-bearing. Cross it intentionally or maintain the duplication yourself.
Trending repository of the day 📈 hallmark by @nutlope Anti-AI-slop design skill for Claude Code, Cursor, and Codex. Last 24h: 2,859 ⭐ Total: 37,891 ⭐️ Nutlope/hallmark