🧑‍🎨
科技与品味3

Quality creates gravity. —— Linear

早上刷 X,看到 a16z 旗下的Cosign 评出了 20 家最有 taste 的公司。Cosign目前还是受邀制,投票人基本是硅谷科技圈一线的创业者、投资人,以及设计师的品味,相对还是有权威性的,大概有700多人参与。 榜首,不出所料是Apple,第二名,让我很惊喜,就是最近关注到的Linear。 这验证了我一直以来关于taste的几个想法: 1. taste绝对不是主观的,而是客观存在的。一家公司有没有taste,不是大家各有所好,而是可以形成共识的。 2. taste 是有极大商业价值的。而且能卖出三种价钱。 第一种是定价权。Apple 2025年财年录得净利率 26.9%,iPhone 全系列平均售价 946 美元,全球智能手机均价刚过 400 美元,是全球行业平均价格的两倍以上。 第二种是产品即推广。Linear 讲过:“一个团队用过 Linear,会告诉别人,采用就会在组织里自然扩散。这条从体验到推荐、到采用、再到忠诚的飞轮,推动我们增长的效果远超任何传统手段。” 所以,Linear 第二年就盈利,基本上没花营销费,2026 年 ARR 做到 1 亿美元。 Midjourney 也走的这条路线,没有融资,没拿投资人一分钱,全靠订阅收入,公测一个月就盈利,2023 年营收 2 亿美元,2025 年 5 亿美元,官网明确团队就60人规模。 第三种是低成本高回报。A24 是纽约的独立电影公司,先做发行,2016 年开始制作电影。片子成本都很低,但品味非常好。 《月光男孩》400 万美元成本,全球票房 6,500 万;《瞬息全宇宙》2,500 万成本,1.43 亿票房; 今年的《Backrooms》约 1,000 万成本,全球票房约 4 亿。 以下是排行榜。 顺便bonjour!有没有可能组织一个类似的评选捏,限定范围在国内AI初创。
🚙 正在研究 jev 团队的官网 团队的核心理念是「Build Prof, Not God」,核心团队一共三位,都是 Research 工程师出身。 Founders: 在“正经”的个人介绍旁边,附带了每人的「Fun Fact」(好像桌面上随手打开的小工具啊!😋),比如小学时候获得国际象棋比赛第44名,23年赢得了7场黑客松比赛、喜欢咖啡因,喜欢玩《炉石传说》🎮 并且曾经打榜到top 2 Culture: 个人感觉水话比较多 🤔 大致的意思就是待遇不错、相互帮助、一起成长,做有意义的事情 Values: 我很喜欢这部分!!!🤩 1. 积极乐观的长期主义伙伴,团队获得胜利的时候,所有人都是赢家 🫵 2. 以赌局的方式思考问题 🤔 良好的决策往往伴随诸多的不确定性,要把长远目标优先于短期利益。(依然坚持长期思维) 3. 第一性原理,希望每一个决定都源于清晰的思考,并且符合价值观和团队文化。(jev 团队真的很喜欢 💅 这个 emoji) 4. 把学习放在首位,成功的关键在于尽可能了解自己、团队、工作流程、产品、市场以及实现目标相关的所有方面。(这点很认同,快速学习是非常重要的,能够应对不同的团队和市场环境) 5. 热爱自己所从事的工作,也想寻找那些同样有热情的人,愿意接受挑战的人! 6. 情感是人类本质的核心组成部分,也是激发我们对所从事工作的热情的源泉。我们制造机器,但并不试图成为机器本身。(aaa 很认同!) 让 Astra 研究了一下这个团队的主页设计风格 👇 GPT:“对!🤓 我会把它归为「复古桌面界面(Retro Desktop UI)+新粗野主义(Neo-brutalism)」的混合风格。” 打孔卡、机械线稿、老电脑的界面风格、现代化的表达... (🤔 好多元素) GPT 说一句话概括整个品牌风格就是—— 计算机历史感 × 复古技术美学 × 一点极客幽默 🤯
读完了linear的why is quality so rare,很受鼓舞,因为他们证明了朴素的正道永远是走得通的,只要能够坚持到底。 我一直觉得对品质的追求是会硬生生把一条赛道劈开,给那些少数有坚持的手艺人单独开辟一条人迹罕至的赛道。在这条赛道上,他们和同行们从事着一样的行业,但却鲜有蓝海变红海之虞,因为这条路缺少竞争者是有原因的:它荆棘丛生,对人的综合素质有严苛的要求。 我的第一份工作就是在这样一家极其注重教学品质的机构。老板和我师父都是新东方摸爬滚打出来的明星教师,并且机构在我去之前已经默默积攒口碑了十一年。老板预感业务要爆发,他们两个老师带不过来,于是打算从北外遴选英语好能考高分的新老师培养来承接大部分的课,就这样,还在读研一的我有了一份让同学羡慕的高收入工作。但是机构对品质和口碑的追求让我并没有那么快就接上很多课。那个暑假,我一边做班课助教熟悉机构的管理和学生的画像,一边在老师上课时备课,并承接零星的一对一来培养我的教学能力和积累经验。经过了严格的磨课和一对一的历练,我终于被允许带了人生第一个班课。我又激动又紧张,但发现自己之前的准备让我在讲台上进入了心流状态。我能从容地接住学生的提问,临机应变想到很多备课时没想到的讲法,再把这些新讲法迭代沉淀进我的课程里。学生也很喜欢我,因为我非常松弛,学生也能感受到我对他们的信心。这种松弛让我能够把课上得非常幽默,那些现挂的笑话让整个课堂充满了欢声笑语,以至于由于隔音不好,隔壁上课的老板时不时就要过来开门扮一下白脸维持秩序。我后来学会了通过控制自己的表情来给课堂降温,以至于学生都惊叹于我怎么能绷得住,一脸正经地讲那么好笑的话。入行的头三年是我教学生涯的高光时刻之一。 尽管如此,直到四年后我离职之前,在面对新学生第一节课之前我依然会非常紧张然后过度准备。只是到了第四年的职业倦怠期,我的过度准备已经变成了出于被投诉的恐惧而进行的固步自封的路径依赖。 后来我的第二任师父把我拉出了职业倦怠,但同时也让我对教学的要求更加严格。因为这位教学总监对老师的要求事无巨细。细到老师的一些无意识口癖和PPT要不要进入全屏,进入全屏以后每页上怎么控制信息量能让学生不分心等等。在他那里这些事情同等重要,这也教会了我如何对待学生:如果不那么重要,那就不要提;只要说了,那就是重要的。 在卷生卷死的北京上海的留学语培行业,尤其是疫情之后,这些也都只是basics,是最最基本的要求。想做得好,还必须能充分燃烧自己的精力。在教师这一行,勤奋是品质的scaler。虽然草台班子也存在,但能长久活下来的都是这种对品质极其偏执的机构。 关于我自己的产品,我也从来不相信“先做个垃圾出来”。因为要不要速度,这也得分情况。对于语言学习app来说,产品的品质本身就是产品定义的一部分,也是区分赛道的依据。换句话说,如果我不把产品的目标做到极致,那MVP就根本不存在,它就只会是一个业余爱好者手搓的玩具,没有人会把自己宝贵的时间和精力浪费在上面。因此,即使我的创业是在与时间赛跑,我也根本无法在质量上妥协。虽然上线以后肯定还要根据用户反馈打磨,但是上线那一刻的品质会决定有没有用户愿意花时间在产品上产生我打磨所需要的反馈。仅就我的产品而言,单纯的上线速度什么都换不来,还会赔掉潜在用户对我的信心。反之如果我足够耐心,我就能走上那条人迹罕至的赛道,专注做我最擅长的事情,那就是设计用户体验,无论用户是学生还是app的使用者。
读了Linear的四篇文章,我愿意称之为最好的品牌故事,最好的产品故事,最好的客户故事。 “Linear第二年就盈利。到第四年,一万多家付费客户,营销投入基本为零。”我是百分百信的,因为只有这样想的人,才能说出这样的话,做到这样的事: “Linear靠质量站了出来。质量产生引力,把人吸过来,不用我们去推。一个团队用过Linear,会告诉别的团队。体验、推荐、使用、忠诚,这个自然飞轮推动增长,比任何传统打法都有效。” 我读的四篇是: Why is quality so rare? — 为什么品质如此稀缺 Why we committed to a zero-bugs policy — 我们为什么执行零bug政策 How Dandelion Chocolate scales craft — Dandelion如何把手艺放大 Output isn't design — 产出不是设计
在给客户做AI初创品牌故事/slogan时,思考哪些科技圈品牌值得参考的时候,第一个跳进脑子里的是暗涌。 暗涌Waves,slogan 是“人的浮沉,钱的流动”。整一套意象都是呼应得很好,跟水有关:人在时代潮流中浮沉,金钱也像水一样流动。 这是形式上的美。 然后再看内容上的美。暗涌聚焦一级市场报道。人和金钱,正是这个地方最重要的信号。 念到暗涌两个字,我总会想到一个画面:一条小船,航行在深夜的茫茫大海中,一束孤独的探照灯,照亮在水下、暗中涌动的庞然大物。 暗处的涌动,也代表着一种势能。一级市场的动向,资本和人才的流动,引领接下来国内的重要创业的方向。它们可能在不久的未来,会掀起惊涛骇浪,带来波澜壮阔,通向星辰大海。 总而言之,暗涌的一整套意象,有种浑圆如弹丸的美感。
新栏目《999 个小技巧,让你 Vibe 的产品更有质感》 ✨ 001 富有点击手感的拟物按钮 Prompt 如下,可以直接抄 ⬇️ Define a tactile, skeuomorphic Button component with five variants, from strongest to weakest: primary, secondary, tertiary, ghost, text. If the project already has a component library or design system, do not add a new component: restyle its existing Button through its own variant and token system, and keep its API, props and accessibility as they are. Otherwise create one reusable Button with `variant` and `size` props. Style: calm and precise, like the Lumno browser extension and the Cloudflare dashboard. Neutral grays only, no brand hues. Lit from straight above. No glossy Web 2.0 shine, no glow, no large blur. Variants: 1. primary - near-black slate face (#404859 -> #273042), white label 2. secondary - raised white key (#FFFFFF -> #F4F5F7), dark gray label 3. tertiary - soft gray key (#F3F4F6 -> #E7E9EC), dark gray label 4. ghost - no face at rest; faint gray fill on hover; a recessed well when pressed 5. text - gray label with a thin underline and an arrow that nudges right on hover Every filled variant is the same five material layers; only the values change, so define them once as tokens and let each variant set its own: 1. Face: 180deg linear gradient, top 6-8% lighter than bottom. 2. Edge: 1px solid border one step darker than the bottom of the face (primary #12161F, secondary rgba(15,23,42,.14), tertiary rgba(15,23,42,.1)). 3. Top highlight: inset 0 1px 0 white (18% on slate, 85-100% on light faces). Put every inset layer in the button's own box-shadow, before the drop layers, never on a pseudo-element overlay: inset shadows on the element follow the inner radius (outer radius minus border), so the corners line up in every state. 4. Bottom shade: inset 0 -1px 0 black (22% on slate, 6% on light faces). 5. Drop shadow in two layers: a tight contact shadow 0 1px 2px plus a soft lift 0 4px 10px -3px (18% and 28% on slate, about a third of that on light faces). States (hover, pressed/active, focus-visible, disabled): - Hover: face one step lighter; the lift grows to 0 8px 16px -5px. - Pressed: translateY(1px); flip the gradient (darker on top); the outer shadow collapses to 0 1px 1px; the top highlight becomes an inner shadow, inset 0 1px 2px black (40% on slate, 12-16% on light faces). Light faces keep a 1px white line below, 0 1px 0 rgba(255,255,255,.9), like a key pressed into paper. - Give rest and pressed the same number of inset layers (pad with inset 0 0 0 transparent) so the shadow animates instead of jumping. - Focus-visible and disabled follow the library's existing conventions. - Timing: 120ms for transform, 140ms for shadows, 160ms for colors. Sizes: all values above are for the 14px label size: height 40px, padding 0 18px, radius 10px, label weight 600, optional 16px leading icon. On the slate face add a label text-shadow 0 -1px 0 rgba(0,0,0,.28). Scale the material with the type, never keep it at fixed pixels: express every length (height, padding, radius, border, icon, the 1px press offset, and every shadow offset, blur and spread) as a multiple of a size unit u = label size / 14. Provide two sizes: md (14px label, u = 1px) and lg (16px label, u = 16/14 px, so height 45.7px, radius 11.4px, lift shadow 0 4.6px 11.4px -3.4px). 尺寸:所有数值均适用于 14 像素的标签。标签的高度为 40 像素。 填充 0,宽度 18px,半径 10px。标签权重 600,可选字体大小 16px,带有图标。 在幻灯片面上添加如下标签样式:text-shadow 0 -1px 0 rgba(0,0,0,.28)。 使用相应的类型来缩放素材,切勿将其固定在固定的像素上:请表达出来。 各种长度(高度、填充、半径、边框、图标、1 像素的鼠标点击偏移量等) 以及每个阴影的偏移量、模糊程度以及扩散情况,所有这些参数都是按照某个尺寸单位来计算的。 u = 标签大小 / 14。提供两种尺寸:md(14 像素的标签,u = 1 像素)和 左图(16 像素标签,上距 16/14 像素,因此高度为 45.7 像素,半径 11.4 像素,带有提升阴影效果) 0 4.6 像素,11.4 像素,-3.4 像素。
新栏目《999 个小技巧,让你 Vibe 的产品更有质感》 ✨ 003 Dither 与 ASCII 参数化效果 001–003 都在我主页,关注我,每天一个让产品更有质感的小技巧 为你的登录页面/卡片添加可控的 Dither 与 ASCII 效果,并附带遮罩、色调、采样强度、大小、间距等可调参数。 两种效果怎么拆: ASCII:把画面切成网格,每格按亮度换成一个字符,从 “.” 到 “@” 越来越密。大小是字号,间距是格子疏密,采样强度是明暗对比,取样区域决定字画的是暗部还是亮部。 Dither:把画面切成像素块,用 4×4 的 Bayer 矩阵当阈值,把每个颜色压成几级。大小是像素块,间距是纹理的尺度,采样强度越高,颜色级数越少,颗粒感越重。 两者都可以加一层遮罩,让画面退后,效果更像纹理而不是噪点。 推荐参数: ASCII:遮罩 90、取样暗部、采样强度 100、大小 37、间距 0 Dither:遮罩 88、采样强度 100、大小 15、间距 0 Prompt 如下,可以直接抄 ⬇️ Add an ASCII / ordered-dither effect to one specific image or video in this project, with a live control panel next to it. Use the asset and the place I name (an , a , or a file path or URL, and the page or section it sits in); ask me if I have not named them. Apply the effect to that asset only, in place: keep its size, position, rounded corners and anything layered on top of it. If the project already has an image or canvas effect pipeline, or slider, segmented-control and panel components, build on them; otherwise create a reusable EffectLayer and EffectPanel. Settings, one object shared by the layer and the panel: { filter: 'ascii' | 'dither', mask, palette, inkTone, strength, size, spacing } Keep separate values per filter, so switching filters brings back that filter's own settings. What each control does in each filter, its range, and the recommended value (ASCII / Dither): Mask effect, 0-100 (90 / 88): a vertical veil over the picture so the effect reads as texture rather than noise. Same in both filters. Color, Original or one of five palettes (Original): gradient-maps the asset's luminance into one color family before filtering. Sample tones, Shadows | Highlights (Shadows; ASCII only, hidden for Dither): which end of the tonal range becomes dense characters. Sampling strength, 0-100 (100 / 100). ASCII: contrast of the tone curve and how bright and opaque the characters are. Dither: how few levels each color channel keeps (8 at 0, 2 at 100) and how fully the quantized color replaces the original. Size, 0-100 (37 / 15). ASCII: font size, 7-24px. Dither: pixel block, 2-9px. Spacing, 0-100 (0 / 0). ASCII: grid step, 8-24px across and 9-26px down, never tighter than the glyphs. Dither: scale of the Bayer pattern, 1-4 blocks per matrix cell. Helpers used throughout: range(v, a, b) = a + (b - a) * v / 100 luminance L = (0.299 R + 0.587 G + 0.114 B) / 255 s = strength / 100 "The box" is the asset's rendered size on the page. Sampling: Cover-fit the asset into the box and draw it into a small sampling canvas (about 480px on the long side), then read it with getImageData. A sample is the pixel under a point in the box, composited over white. With a palette, recolor that canvas first: map each pixel's L through a 256-entry lookup built from the palette's four stops. Per image or video frame, take about 12,000 evenly spaced samples: low = 8th percentile of L, high = 92nd percentile. Shadows means dark ink, Highlights light ink. ASCII: Characters, from empty to full: " .,:;-=+xX08S#&@" (starts with two spaces). Font: round(range(size, 7, 24))px monospace (22 instead of 24 when the box is under 720px wide), centered in each cell. Grid: x step = max(range(spacing, 8, 24), widest glyph * 1.08); line height = max(range(spacing, 9, 26), height of "@" * 1.12, font * 1.04). The first cell sits half a step in from the edge. Tone of a cell: raw = dark ink ? 1 - L : L; normalized = dark ink ? (high - L) / (high - low) : (L - low) / (high - low), clamped 0-1 (use raw alone when high - low < 0.025); mix = 0.72 + 0.14 s; t = raw (1 - mix) + normalized mix. Then a tone curve: black = 0.22 s, white = 1 - 0.08 s, lev = clamp((t - black) / (white - black), 0, 1), tone = lev (1 - s) + smoothstep(lev) s. Skip cells with tone <= 0.02. Character = chars[round(tone * 16)]; skip spaces. Ink: the sampled color lifted in HSV: value += (1 - value) * (0.24 + 0.18 s + 0.24 tone); saturation *= 1 + 0.16 + 0.2 s (clamped). Alpha = clamp((0.12 + 0.7 tone) (0.72 + 0.28 s), 0.06, 0.94). Dither (ordered, Bayer 4x4): pixel size = max(2, round(range(size, 2, 9))) (7 instead of 9 under 720px); pattern scale = max(1, round(range(spacing, 1, 4))); levels = max(2, round(range(strength, 8, 2))) per channel; blend = range(strength, 0.32, 1). Matrix [[0,8,2,10],[12,4,14,6],[3,11,1,9],[15,7,13,5]]; threshold = (m + 0.5) / 16, indexed by floor(x / pattern scale), floor(y / pattern scale). For each block sample its center, push saturation away from luma by 1 + 0.06 + 0.18 s, then per channel: scaled = c / 255 * (levels - 1); q = floor(scaled) + (fraction > threshold ? 1 : 0); out = c + (q / (levels - 1) * 255 - c) * blend. Write the blocks into a canvas of box / pixel size and draw it scaled up with image smoothing off. Mask and layering: The mask is a vertical gradient with stops at the top, 42% and the bottom. Base opacities: on a light page white 54/20/38%, on a dark page black 44/20/50%. For a mask value v: stop = v <= 50 ? base * (v / 50)^1.08 : base + (100 - base) * ((
在做AI初创品牌语言过程中,试图找下参考。 之前讲了喜欢暗涌,elsewhere我也很喜欢,毕竟是同一个团队。跟郭老师聊过几次,他真的好有品.....!!!非常喜欢的前辈。 Elsewhere 是刘旌老师离开暗涌之后做的创投媒体品牌,中文叫别处发生,slogan 是 Maybe Wrong Always Fun。 他对elsewhere有两层解释:创新常常发生在意想不到的地方,以及做真正重要、有意思的商业科技内容。 虽然出自于同一位主编之手,Elsewhere的气质跟暗涌很不一样。 暗涌念起来有鼻音,是往下沉的,有分量;elsewhere 念起来有一种丝滑轻弹的感觉,像会在阳光下飞起来的轻巧纸飞机。 报道的风格也更加年轻化,比如除了头部VC合伙人访谈之外,还有elselier这个聚焦年轻初创founder的栏目。 Elsewhere的创刊词,提到了“看见行业和人的另一面”,我也很喜欢这个角度。 品牌Stroytelling,不至于沦为“讲故事、说大话”的前提是,把叙事当战略来落地。 最近的田柯宇事件,就是一个很好的例子。 它本质上是提供了一个窗口,报道其他渠道还没有触碰到的东西,我觉得这就很好地完成了使命。 网上很多的指责和谩骂声,我认为是不那么公平的。 在田之外,补充更多视角,这是在执行层可优化的地方。可以指出和建议,但绝没必要上升到大面积的攻击。应该给媒体讲话的空间,毕竟没人想看锣鼓喧天的AI产出。 话题有点跑远了。 总之,我非常欣赏暗涌和Elsewhere的一整套品牌内容,之后有空再来拆解为什么它们还特别符合传播原则。 毕竟,从36氪出走的高职级不少,但像刘旌和团队一样,用大半年把elsewhere做到现在的品牌影响力,也就独此一家了。
「天气简报」在第一屏承担了用户对当前天气的「第一感知」,不用看图标、温度和文字。「晴朗舒适」的天气是「明黄色」、「雨天」是「灰蓝色」、「云多」时是「冷灰色」、「晴朗的晚间」则是「通透的深蓝色」…… 这些颜色贯穿了App页面和小组件页面,如果你使用iPhone Duo,把手机转换到「帐篷模式」,还可以把屏幕变成「一扇有天气情绪的窗」。 RAWeather会根据所选城市的真实太阳/月亮角度,模拟光照角度。因此「天气主题色」和「页面中的每个模块」都会感知光的来源,并做出相应的光照反应。