iArt.ai
AI 모션 그래픽 소프트웨어, 누구나 사용할 수 있는 After Effects 대안, 텍스트 프롬프트로 몇 분 안에 애니메이션·설명 영상 제작
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗This is the marketing website for Pinecast. It currently deploys to www-next.pinecast.com.
First, run the development server:
npm run dev
Open http://localhost:3000 with your browser to see the result.
npm run lint # ESLint, with the jsx-a11y recommended rules
npx tsc --noEmit
npm run build # static export to out/
npm run check:structure # headings, lists and alt text in out/
npm test # Playwright: keyboard, landmark, axe, reflow, text spacing
# and target size checks on out/
npm test serves out/, so build first. It needs Playwright's Chromium once:
npx playwright install chromium.
The identity lives in this repo as the --color-* block in
src/pages/_document.tsx, the faces in src/fonts.ts, and the type roles in
src/components/Typography.tsx. The Figma file behind it records conventions
the code does not — see docs/figma-workflow.md for how
to read it, and for the places the two have drifted apart.
Each page has one <h1>, and heading levels don't skip. The heading
components in src/components/Typography.tsx and src/components/TextBlocks.tsx
take a level prop that picks the element separately from the look, so move a
heading in the outline with level, not by switching to another component. In
MDX, the number of # still picks the look, and
vendor/rehype-heading-levels.mjs sets each heading's level from the outline
under the page title.
After a build, npm run check:structure reads the static export in out/. It
fails if a page doesn't have exactly one <h1>, skips a heading level, puts
something other than <li> in a list, or has an <iframe> with no title or an
<img> with no alt. It also fails if two different screenshots share the
same alt text.
npm run build && npm run check:structure
The "Pause animations" toggle in the header pauses every animation that starts
by itself and runs for more than five seconds (WCAG 2.2.2). Each animation
stops where it is: do not show a still image in its place. With
prefers-reduced-motion: reduce, the animations start paused, and the user can
still play them. src/hooks/useMotion.ts holds the state, and keeps the choice
in localStorage. A choice to pause always holds. A choice to play holds only
under the reduced motion setting that it was made under, so a user who turns on
reduced motion later gets paused animations again.
When you add an animation:
loopingAnimationProps on the element. The
style block in src/pages/_document.tsx pauses it. Reduced motion stops all
other CSS animations and transitions at their end.introAnimationProps on the element. While the toggle is on, it shows its
end at once, as all of them do with reduced motion.useCanvasDrawing and
useAsyncVideo. They follow the toggle. Read isMotionPaused(), not the
paused value of useMotion, in code that starts or stops media: in the
first render in the browser, paused is still the value of the static
export.<video> on the page: use NoncriticalVideo. Do not give it autoPlay.reducedMotion of useMotion), as the page heroes, the home hero and
the globe do.tests/motion.spec.ts checks each kind.
The toggle shows its pressed state as a filled square with a light icon (the
colors of the header reversed). The focus ring is an outline around the icon.
So, the four combinations of pressed and focused all look different, and the
pressed toggle does not look like a focus ring. The toggle has a tooltip, like
the one of the mute button (Tooltip). tests/motion-toggle.spec.ts checks
the four states and the tooltip.
A tooltip stays open while the pointer goes to it (WCAG 1.4.13). The bridge
under the tooltip covers the gap, and the "safe area" covers the rest: while
the pointer is inside the convex shape of its last place on the control and the
tooltip, the tooltip stays open. So, the pointer can go on a straight line from
any part of a control, also one that is taller or narrower than its tooltip,
to each part of the tooltip. A pointer that goes away, or jumps away, closes
it at once. Tooltip does this, so each tooltip of the site has it.
tests/motion-toggle.spec.ts moves the pointer 1px at a time to check it.
The user sees the hero first. A tile of the hero is purple or lime until its still image is in. So the stills load first, and nothing that can wait uses the bandwidth until they are in.
src/heroStills.ts lists the stills and the layouts that draw them. Mobile
draws one (central), tablet five and desktop seven.src/pages/_document.tsx preloads them, each one with the media of the
layouts that draw it. HeroV2 loads the same stills (useAsyncImage), and
only the ones that its layout draws. The CSS skeleton of the hero shows them
too, so the user sees a still when it is in, before the page script runs.
The canvas reads img.complete (isReady in src/canvasHelpers.ts), so it
does not paint a placeholder over a still that the skeleton showed.src/hooks/useLoadOrder.ts makes the rest wait. An image that calls
markCritical (the stills) holds back each hook that calls
useAfterCritical, until the image loads or fails. These wait: the sounds,
the videos of the hero and of the globe, the image of the globe, the prefetch
of the footer video, NoncriticalVideo (preload="none" until then) and
the art of the header menu. The sounds also start at the first key press or
pointer press, so a sound is there when the user asks for it. A page without
critical images opens the gate after its first render, so on the other pages,
nothing waits.Two rules keep the stills from slowing the page script. The hero needs the script to take over from its CSS layout, and the menu and the buttons need it too.
fetchpriority="low". At the normal or the high priority,
the stills took the connections first. At 4 Mbps and 150 ms, the canvas took
over at 5 to 8 s, not at 1.5 s.<head>. A browser asks for files
in the order of the page, and it has six connections to a server that speaks
HTTP/1.1. React moves a <link> to the start of the <head> unless it has an
event handler, so the stills have a handler that does nothing.The posters of the videos of TunedIn are data URIs, not files: a blurred copy
of the art, 32 px wide and about 0.5 KB, in src/posterPlaceholders.ts. They
are in the static page, so they show from the first paint (also without
JavaScript) and cost no request. The posters were three PNGs of 800 KB each, and
they took the bandwidth that the stills needed. When the art in
public/images/art/ changes, run node scripts/generate-poster-placeholders.mjs
and commit the file that it writes.
tests/hero-loading.spec.ts checks the preloads, the order of the requests,
and the change from the CSS layout to the canvas. To measure the times on a
slow connection (4 Mbps and 150 ms by default, a cold cache):
npm run build
node scripts/measure-hero-loading.mjs out --runs 3 --width 1440 --height 900
It also takes --width 1024 (tablet), --width 390 (mobile), --filmstrip
(the share of the viewport that is still a placeholder color) and a
CHROMIUM_PATH for a browser other than the one of Playwright. To compare two
versions, build each one, copy out/ aside, and run it on each copy.
The globe on the home page shows one feature at a time, as the page scrolls.
The "Learn more" link of each feature is the keyboard path: Tab goes to each one
one time. The three links on the globe (Distribution, Analytics, Monetization)
are for the pointer and for screen readers. They have tabIndex={-1}.
When Tab gives a "Learn more" link focus, the page scrolls to the middle of the
scroll range of its feature (FEATURE_SCROLL_RANGES in Globe.tsx), so that
the globe and the text match. The scroll is smooth. It is at once under reduced
motion and while the animations are paused (getScrollBehavior in
src/hooks/useMotion.ts). Focus that Tab did not give does not scroll the
page, and the mouse does what it did before.
tests/globe-keyboard.spec.ts checks this.
Two rules keep this stable on a busy page:
isTabPress in
Globe.tsx), not by the time stamps of the key and of the focus. The time
stamp of a key press is the time of the press. A busy page gets it some
hundreds of milliseconds later, and then a window of 100 ms is too short.stopScroll
(src/hooks/useMotion.ts), as the globe and the Play buttons of the
testimonials do. The browser scrolls (smooth) to the control that had focus
before, and under load that scroll can start late. A smooth scroll to the
place where the page still is does not stop it, and then the old scroll takes
the page away from the new place.