2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

未経験の"最初の1個"に何を作るか — AIと作りやすい小規模アプリ3パターンの要件・プロンプト・つまずき

2
Posted at

プログラミング未経験の人が「AIがあれば作れるらしい」と聞いて Claude Code を入れて、最初の10分で止まる。理由はエラーでも環境構築でもなく、「で、何を作ればいいの?」 です。

作りたいものがある人は迷いません。問題は「特にない」人。ここで多くの入門記事は「やりたいことを言葉にしよう」で終わりますが、それができないから止まっているわけで、抽象論を重ねても前に進みません。

この記事では方法論ではなく、具体的に作るものを3つそのまま渡します。それぞれについて「AIにこう頼む」というプロンプト文面と、返ってくるコードの骨子、未経験が必ず1回詰まるポイントを付けます。全部 Next.js(App Router)+ TypeScript 前提で、コピペしながら読めるようにしています。


そもそも「最初の1個」に向くアプリの条件

何でもいいわけではありません。最初の1個で挫折しないアプリには共通点があります。

  1. 小さい:1〜2画面で作り切れる。3画面以上・ログイン必須・決済ありは2個目以降に回す
  2. CRUDの基本が入る:作る(Create)・表示する(Read)・消す(Delete)が一通り体験できる。ここが「アプリを作る」の骨格なので、最初に通しておくと2個目以降が一気に楽になる
  3. 達成感が出る:自分が毎日使えるもの。他人のためではなく「自分の買い物メモ」だと、動いた瞬間に嬉しいし、機能追加のモチベも続く

この3条件を満たす具体案が、次の3つです。

# アプリ 覚える技術の骨 詰まりやすい1点
1 買い物・家計メモ useState / 配列操作 / map リロードで消える
2 読書・映画の記録リスト localStorage / useEffect サーバー側で localStorage は使えない
3 よく使うリンク集+検索 filter / 入力連動 大文字小文字・部分一致

段々と難しくなる順に並べてあります。1→2→3で「消えないデータ」「絞り込み」と一歩ずつ増えるので、上から順にやるのがおすすめです。


パターン1:買い物・家計メモ(メモCRUD)

① どんなアプリか

入力欄に「牛乳」と打ってボタンを押すとリストに追加され、横の×で消せる。それだけ。CRUD の Create / Read / Delete をこの1画面で全部触れるのが狙いです。Update(編集)はあえて省きます。最初の1個に編集機能はいりません。

② AIへの依頼プロンプト例

Claude Code にそのまま貼れる粒度で書きます。ポイントは**「使う技術」「画面の見た目」「やってほしくないこと」を1回で伝える**こと。

Next.js(App Router, TypeScript)で、買い物メモの1画面を作ってください。

- テキスト入力欄と「追加」ボタンがある
- 追加するとその下のリストに項目が増える
- 各項目の右に「×」があり、押すとその項目だけ消える
- データの保存はまだ不要。useState だけで、ページ内で動けばOK
- ライブラリは新しく入れず、標準の React と Tailwind だけで
- ファイルは app/page.tsx 1つにまとめて、全文を出してください

最後の「1ファイルに」「全文を」が地味に効きます。未経験のうちは、複数ファイルに分割されると「どこに何を貼るのか」で迷子になるので、最初は1ファイルに寄せてもらうのが安全です。

③ 返ってくるコードの骨子

だいたいこういう形が返ります。読めなくていいので「形」だけ眺めてください。

"use client";
import { useState } from "react";

export default function Page() {
  const [items, setItems] = useState<string[]>([]);
  const [text, setText] = useState("");

  const add = () => {
    if (!text.trim()) return;      // 空は追加しない
    setItems([...items, text]);    // 配列の末尾に足す
    setText("");                   // 入力欄を空に戻す
  };

  const remove = (index: number) => {
    setItems(items.filter((_, i) => i !== index)); // その番号だけ除く
  };

  return (
    <main className="max-w-md mx-auto p-6">
      <div className="flex gap-2">
        <input
          className="border p-2 flex-1"
          value={text}
          onChange={(e) => setText(e.target.value)}
        />
        <button className="bg-blue-600 text-white px-4" onClick={add}>
          追加
        </button>
      </div>
      <ul className="mt-4 space-y-1">
        {items.map((item, i) => (
          <li key={i} className="flex justify-between border-b py-1">
            <span>{item}</span>
            <button onClick={() => remove(i)}>×</button>
          </li>
        ))}
      </ul>
    </main>
  );
}

覚えるのは3つだけです。useState(画面が覚えておく箱)、map(配列を画面に並べる)、filter(条件に合うものだけ残す)。これが CRUD の Create / Read / Delete に対応しています。

④ 未経験が必ず詰まる1点

ページをリロードするとメモが全部消える。「バグでは?」と焦りますが、正常です。useState はメモリ上に置いているだけで、リロードすると初期化されます。ここで「保存とは何か」に自然に興味が向くので、そのままパターン2に進みます。詰まったら、こう聞けばいい。

このメモ、ページをリロードすると消えてしまいます。
リロードしても残るようにするには、次に何を学べばいいですか?
コードはまだ変えず、選択肢と理由だけ先に教えてください。

パターン2:読書・映画の記録リスト(localStorage で保存)

① どんなアプリか

観た映画・読んだ本のタイトルと一言メモを記録していく。パターン1との違いはリロードしても消えないこと。ここで初めて「保存」を体験します。保存先はブラウザ内の localStorage。サーバーもデータベースもまだ不要なので、未経験が「保存」に初めて触るのにちょうどいい踏み台です。

② AIへの依頼プロンプト例

パターン1のコードがある前提で、差分をお願いする形が綺麗です。

今の買い物メモのコードをベースに、読書記録アプリに変えてください。

- 1項目は「タイトル」と「一言メモ」の2つを持つ
- 追加・削除は今と同じ操作感で
- ★重要:追加・削除した内容を localStorage に保存し、
  リロードしても復元されるようにしてください
- 保存キーは "reading-log" にしてください
- localStorage を読む処理は、ブラウザでだけ動くように注意してください

最後の1行がないと、後述の詰まりポイントを踏みます。先回りで釘を刺しておくとAIの出力が安定します。

③ 返ってくるコードの骨子

保存と復元は useEffect の2箇所で組むのが定番です。

"use client";
import { useState, useEffect } from "react";

type Log = { title: string; note: string };
const KEY = "reading-log";

export default function Page() {
  const [logs, setLogs] = useState<Log[]>([]);

  // 起動時:localStorage から読み込む(ブラウザでだけ動く)
  useEffect(() => {
    const saved = localStorage.getItem(KEY);
    if (saved) setLogs(JSON.parse(saved));
  }, []);

  // logs が変わるたび:localStorage に書き戻す
  useEffect(() => {
    localStorage.setItem(KEY, JSON.stringify(logs));
  }, [logs]);

  // add / remove は パターン1と同じ発想(省略)
  // ...
}

JSON.stringify で配列を文字列にして保存し、JSON.parse で戻す。この往復が「データを保存する」の最小形です。

④ 未経験が必ず詰まる1点

「localStorage is not defined」で真っ赤になる。 Next.js の App Router はコンポーネントを最初サーバー側で動かそうとしますが、localStorage はブラウザにしか存在しません。だから「サーバーには localStorage なんて無いよ」と怒られる。

対処は2つ。ファイル先頭に "use client"; を書くこと、そして localStorage を触る処理を useEffect の中に入れること(useEffect はブラウザでしか走らないため)。上のコードは両方やっています。ここは未経験がほぼ100%踏むので、踏んだら成長のサインです。詰まったらエラー文をそのまま貼って聞けば直せます。

「localStorage is not defined」というエラーが出ました。
原因を初心者にわかる言葉で説明して、直したコードを出してください。

パターン3:よく使うリンク集+検索フィルタ

① どんなアプリか

自分がよく開くサイト(ドキュメント、管理画面、SNSなど)を登録しておき、上の検索欄に文字を打つとリアルタイムで絞り込まれる。パターン2までに「保存」を覚えたので、今回は「絞り込み(フィルタ)」を足します。入力に連動して表示が変わる、いわゆる"動くUI"の入り口です。

② AIへの依頼プロンプト例

リンク集アプリを作ってください(Next.js App Router / TypeScript)。

- 1項目は「名前」と「URL」を持ち、名前はリンクとしてクリックできる
- 追加・削除ができ、内容は localStorage に保存(キー "links")
- ★上部に検索ボックスを置き、入力した文字を「名前」に含む
  項目だけをリアルタイムで表示する(部分一致・大文字小文字は区別しない)
- 検索欄が空のときは全件表示

③ 返ってくるコードの骨子

絞り込みは「元の配列はいじらず、表示する直前に filter する」のが鉄則です。

const [links, setLinks] = useState<Link[]>([]);
const [query, setQuery] = useState("");

// 表示用に絞り込む(元データ links はそのまま)
const shown = links.filter((l) =>
  l.name.toLowerCase().includes(query.toLowerCase())
);

return (
  <main>
    <input
      placeholder="検索..."
      value={query}
      onChange={(e) => setQuery(e.target.value)}
    />
    <ul>
      {shown.map((l, i) => (
        <li key={i}>
          <a href={l.url} target="_blank">{l.name}</a>
        </li>
      ))}
    </ul>
  </main>
);

ポイントは、links を書き換えず、表示用の shown を毎回作り直していること。検索でデータそのものを消してしまうと、検索欄を空にしても戻ってこなくなります。

④ 未経験が必ず詰まる1点

大文字で登録したのに小文字で検索するとヒットしない。 includes は大文字小文字を区別するので、「GitHub」は「github」で検索しても引っかかりません。両方を .toLowerCase() で小文字に揃えてから比較する、という一手間が要ります。上のコードで l.name.toLowerCase() と query.toLowerCase() の両方を小文字化しているのはこのためです。「検索が思ったより効かない」の9割はここです。


3つ作り終えたら、次の一歩

3つ通すと、useState(画面の状態)・localStorage(保存)・filter(絞り込み)という、アプリの土台が体で分かります。ここまで来たら次は**「ブラウザを閉じても・別の端末からでも消えないデータ」**、つまりサーバー側のデータベースです。

localStorage は「そのブラウザの中だけ」の保存なので、スマホから見ると空っぽ。ここで Supabase(データベース + 認証)に置き換えると、"自分だけのメモ"が"どこからでも使えるアプリ"に化けます。プロンプトの粒度は今回と同じでいい。

今の読書記録アプリの保存先を、localStorage から Supabase に移したいです。
まずテーブル設計と、必要な準備の手順だけを、初心者向けに順番に教えてください。
コードはその後で1ステップずつ出してください。

「いきなり全部書かせず、手順→1ステップずつ」に頼むのが、未経験がAIと組むときの一番の安全策です。作るものが具体的でさえあれば、AIは驚くほど正確に付き合ってくれます。止まっていたのは実力ではなく、「何を」が無かっただけです。まずは3つのうち、一番自分が毎日使いそうなものから始めてください。


Qiita の読者の方には、ここで扱った CRUD / localStorage / filter は当然すぎる内容だったと思います。もしプログラミングを始めたばかりの知り合いや、独学で「何を作ればいいか分からない」と止まっている後輩がいたら、この記事を最初の1個の選択肢として渡してもらえると嬉しいです。社内の新人研修の"はじめの一歩"としても使えます。

未経験者向けには、未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全20セッションで体系化した教材を運営しています。作るだけでなく「AIに正しく頼む力・出力を見る目」まで身につく設計です。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?