v0 + Cursor + Next.js ファーストインプレッション

v0 は Next.js の開発元 Vercel 社が提供する AI ベースのウェブデザイン特化型のプロトタイピングサービスです。Cursor は AI による支援機能を搭載したコードエディタです。

本記事では v0 でプロトタイピングしたコードをローカルに移し、続きを Cursor エディタで開発するという一連の流れで、使用感をレビューします。また、Next.js の初心者として、AI のサポートを受けながら進めていく上での最低限必要な知識についてもまとめます。

# v0

https://v0.dev/chat

v0 の主要機能は v0.dev/chat と呼ばれる AI チャットインターフェースです。このチャットを通じて、ユーザーは自然言語でデザインの指示を行うことができます。AI がこの指示を解釈し、対応する Next.js のコードを自動生成します。

デザインを開始すると、画面が左右に二分割され、右側にデザインが表示されます。Claude のアーティファクトと同じような動作イメージです。v0 は Next.js に特化したモデルを使用しているため、汎用的な Claude よりも専門的なコードが生成されると感じました。専属のデザイナーに依頼しているような気分です。

無料枠は回数制限が厳しいですが、日単位で管理されているため、上限に達しても翌日にリセットされます。また、v0 で基本的なプロトタイピングを済ませてしまえば、ローカルにコードを移して開発を続行できます。

## ローカル移行

右上にある Install ボタンを押すと、ローカルに移行するためのコマンドが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32057/4e9a08ee-dacd-d62a-1620-d3882cc422a6.png)

```text
npx shadcn@latest add "(URL)"
```

これを実行すれば、ローカルでの開発に必要なコード一式が構築されます。自動で git のリポジトリが作成されますが、v0 による変更はコミットされていないため、まず最初にコミットしておくと良いでしょう。

# Cursor

ローカルでも AI を活用したコード生成を行うため、Cursor エディタを使用します。

https://www.cursor.com/

Cursor は、VS Code をベースに開発され、インテリジェントな自動補完機能や自然言語によるコード編集機能を提供します。AI とのチャット機能を通じて、開発者はコードベースに関する質問をしたり、バグの検出を依頼したりできます。

AI 機能を利用するにはユーザー登録が必要です。登録後の 2 週間は自動的に Pro の試用期間となります。

## 試用期間終了後

Pro の試用には課金情報の登録は不要のため、試用期間終了後に自動的に課金されることはありません。

それまで使ったカウントは残ったままになります。参考までに、私の状況を示します。

- https://www.cursor.com/settings

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32057/8820a040-ff1b-2467-c76e-b14d4d47708a.png)

:::note info
利用枠は毎月リセットされます。
:::

フリー版での補完は 2,000 回までとなっています。カウントは確認できませんが、試用期間中にそれ以上使っていれば、期間終了時に Cursor 側で、機能をオフにするか課金するようにというメッセージが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32057/aaa92008-7815-d112-d638-467a341a6805.png)

オフにすれば、とりあえず使い続けることは可能です。

その他、無料版を使い続ける場合の設定については、次の記事を参照してください。

https://qiita.com/7shi/items/2e8e3ed2c39e3dc4ee22

## チャットによるコード生成

:::note info
ここから先は、Pro の試用期間中でのレビューです。
:::

Cursor では、コード生成の際に、ユーザーのコードベースに対して変更を加えることができます。

チャットでのコード生成は 2 通りの粒度で進めます。

* [Ctrl]+[K]  
  コード中で局所的に生成・修正。Copilot の [Ctrl]+[I] と同じような機能ですが、追加指示で段階的に絞り込んでいくことを想定した UI になっており、Cursor の方がより実用に即して作り込まれていると感じました。絞り込む過程は便利ですが、使用回数をカジュアルに消費するため注意が必要です。
* [Ctrl]+[L] (AI Chat)  
  コード全体に対して生成・修正。複数個所に渡るような指示に対しても対応できます。
  * `@Codebase` というメンションを使用すれば、開いているフォルダ全体に対する RAG が利用できます。RAG のインデックスは自動的に生成されます。
  * `@Web` というメンションを使用すれば、Web 検索の結果が回答に使用されます。

v0 や Claude でのアーティファクトは、毎回コード全体を生成するためオーバーヘッドが大きいですが、Cursor では編集中のコードに対して変更を適用することができるためスマートです。変更が多岐にわたる場合、Composer という機能でまとめて適用することが可能です。これらの点が、エディタに AI を組み込んだ場合の優位性だと感じました。

:::note info
Composer ではファイル全体が走査されてガシガシと書き換えが始まるため、なかなか壮観です。人間が承認するまでは実際の適用は保留され、提案として差分が表示されます。
:::

大まかな機能をざっくり組み上げる段階では「指示 → 提案 → 承認」の流れで開発を進めることができます。v0 でも指示によって組み上げる点は同じですが、Cursor では提案に対する承認によって制御できる点が優れていると感じました。

## 補完によるコード生成

チャットベースでの指示では、小回りが利かないようなケースにもしばしば遭遇するため、完全に AI 任せというわけにはいきません。ある程度枠組みが固まれば、細かい部分を手動で編集する必要も出て来ます。

その際、GitHub Copilot と同じような、コンテキストに沿った自動補完が利用できます。Copilot では行の途中での補完は行いませんが、Cursor では行の途中でも補完が可能なため、より積極的な印象を受けます。

Cursor では、補完だけでなく修正の提案も行われます。例えば、同じパターンの行が続く場合、最初の行への修正にならって後続の行の修正が提案されます。

## コミット

VS Code ベースのため、VS Code と同様の git 統合が利用できます。

AI Chat でメンションから Git → Commit (Diff of Working State) を選択して「コミットメッセージを作成してください。」と指示すれば、コミットメッセージの作成も行えます。

英語で作成することもできるため、国際的なプロジェクトにコミットする時は重宝しそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32057/dadef3e8-4a18-00b6-2a3d-d58eba459374.png)

## v0 との使い分け

v0 はデザインに特化しているため、ゼロからデザインを組み上げるプロトタイピング段階では優れています。Cursor は小回りが利くため、続きの開発ではより便利に使えます。両方を適当なタイミングで切り替えることで、開発効率が高められるのではないでしょうか。

:::note info
私の場合、v0 の無料枠の制限に達した後、その先は Cursor に移行するという感じになりました。
:::

## GitHub Copilot との比較

インラインチャットでの生成・修正や、チャット欄からのコードへの適用などは Copilot でも行えます。適用が大規模になる場合、Cursor では Composer という機能でまとめて適用することが可能です。

Cursor では補完の頻度がより高く、修正の提案も随時行うなど、より積極的な印象があります。

~~Copilot には Cursor の Codebase のような RAG 機能はありません。~~【実装済】

~~上位エディションの GitHub Copilot Workspace には同様の機能があるようですが未確認です。~~【間違い】

Cursor は Copilot の機能をほぼ含んでいますが、Copilot から Cursor に乗り換えると料金も倍になるため、差分となる機能を活用するかどうかで判断することになるでしょう。

:::note info
個人的には、今まで Copilot は補完機能だけを集中的に使って来ました。Cursor と同様にチャット欄からのコード適用なども実装されていることに気付き、活用しきれていなかったと感じました。
:::

# Next.js

v0 では Next.js が使用されるため、必然的に Next.js の知識が必要となります。Next.js は React をベースにしているため、React の知識も必要です。私はいわゆる Vanilla JS は多少知っていましたが、React や Next.js の予備知識はありませんでした。

Web での動的な表現が当たり前になっている現在、以前なら静的な HTML を手書きしていたようなケースでも、フレームワークを利用するのが普通になっていくような気はします。業務として求められる水準の知識を習得するには相応のコストが掛かりますが、本記事はあまり詳細には立ち入らず、Next.js を使うのに必要となる最低限の知識をまとめます。

:::note info
実際に触ってみた感想として、AI に指示してコードを書いてもらったり、分からない部分を質問したりすれば、個人がちょっとした HTML や JavaScript を書くような感覚の延長線上で、いきなり Next.js を使い始めることも決して不可能ではないと感じました。v0 や Cursor が存在しなければ、このような導入は現実的ではなかったでしょう。
:::

:::note warn
AI に指示した変更が、必ずしもうまく機能するとは限りません。おかしくなった場合、修正箇所を個別に確認しながら問題点を絞り込んだり、修正内容について突っ込んだ質問をしたりすることも必要となります。また、大規模な変更の前には git でコミットして、いつでも戻せるようにしておくことも重要です。
:::

## TSX

React では JavaScript の中に HTML タグを直接記述できるように拡張した JSX を使用します。Next.js ではこの JSX に TypeScript の型定義を組み合わせた TSX を使用します。

v0 で編集していた TSX ファイルは components ディレクトリにあります。引き続いての開発は、ほぼこのファイルだけを書き換えることになります。

TypeScript は JavaScript のような型定義のない書き方をしても一応動くため、とりあえず JavaScript の知識で使い始めることが可能です。

:::note warn
型を曖昧なまま進めると、リリース段階のビルドで型エラーになることがあります。詳細は後述します。
:::

## サーバー

Next.js では、開発時の動作確認にサーバーを使用します。以下のコマンドでサーバーを起動します。

```text
npm run dev
```

ブラウザで http://localhost:3000 にアクセスすると、開発していた TSX ファイルによってレンダリングされたコンテンツが表示されます。

v0 でデザインしたコードは、基本的にフロントエンドとバックエンドを分けるようなコードではなく、フロントエンドだけで完結する内容です。それなのになぜわざわざサーバーを必要とするのかと思いましたが、これには開発の利便性が関わるようです。

具体的には、サーバーの起動中に TSX ファイルを更新すれば、UI が更新されるタイミングで自動的に反映されるため、ブラウザをリロードする手間がありません。細かいデザインの変更が即座に反映されるのは便利です。このような利便性を実現するためにサーバーが利用されていると考えれば納得できます。

:::note info
もちろん他にも理由はあると思いますが、触った範囲での所感です。
:::

:::note warn
UI とは別に状態を持っている場合、それに対する変更は自動で反映できません。動きがおかしくなった場合はリロードしてみてください。
:::

## ビルド

開発の区切りが付けば、デプロイ用のコードを生成するためにビルドを行います。フロントエンドだけで完結する内容であれば、専用のサーバーを必要としない構成でビルドできます。

以前の Next.js のバージョンでは `npx next export` としてコマンドを分けていたようで、検索するとその内容が出て来ますが、記事執筆時の v14.2.8 で試すと方法が変わったと表示されます。

```text
$ npx next export
 ⨯
    `next export` has been removed in favor of 'output: export' in next.config.js.
Learn more: https://nextjs.org/docs/app/building-your-application/deploying/static-exports
```

手元にあったコードベースではファイル名が next.config.mjs となっており、それを以下のように書き換えました。

```javascript:next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
    output: 'export',
};

export default nextConfig;
```

以下のコマンドでビルドすれば、`out` ディレクトリに静的な HTML やスクリプトなどが生成されます。

```text
npx next build
```

### 型エラー

ビルドでは型が厳密にチェックされます。開発時に動いていたコードでも弾かれることがあります。

私が試したケースでは、v0 が出力したコードが引っ掛かったため、AI の助けを借りながら修正しました。一部を引用します。

- https://github.com/7shi/netsim-nextjs/commit/3920f39e799bfdac9b667f982f916778d65a77da

```diff
@@ -250,7 +250,13 @@ export function NetworkSimulator() {
         <Button onClick={addVM} className="mb-4">Add Virtual Machine</Button>
         <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4 mb-8 relative">
           {vms.map(vm => (
-            <Card key={vm.id} className="p-2" ref={el => vmRefs.current[vm.id] = el}>
+            <Card key={vm.id} className="p-2" ref={el => {
+              if (el) {
+                vmRefs.current[vm.id] = el
+              } else {
+                delete vmRefs.current[vm.id]
+              }
+            }}>
               <CardContent className="p-2">
                 <div className="flex items-center justify-between mb-2">
                   <span className="text-sm font-medium">{vm.name}</span>
```

:::note info
このように v0 のコードがエラーになるケースがあることから、ローカルに持って来たらまずビルドして、エラーを修正する所から始めるのが無難でしょう。
:::

## デプロイ

生成された HTML は任意のパスに置けますが、_next ディレクトリがルートに置かれることを前提としています。

手っ取り早く動作確認するには、out ディレクトリで Python の簡易サーバーを起動します。

```text
python -m http.server -d out 3000
```

index.html で指定される `/_next/` を `_next/` に書き換えれば、ローカルでファイルから開いても機能します。

```text:コマンド例
sed -i 's|/_next/|_next/|g' out/index.html > out/index-rel.html
```

# おわりに

この記事は試験的に Cursor で書いています。一応、日本語の文章でも補完や修正の対象になります。ただし文章はコードほどコンテキストが明確ではないため、そのまま使えるケースは少なかったです。コマンドを生成したり、下書きとして機能などを列挙するような用途では、そこそこ使えるのではないかと思いました。