🍼

Nuxt 3 × MongoDBでつくる地域子育てポータルの構築と運用

に公開

はじめに

こんにちは、田中涼平(@RyoheiTanaka)です。

今回は、僕が個人開発した「子育てポータル」についてご紹介します。

🔗 サイトリンク:https://kosodate-portal.coolat.net

このアプリは、自身の子育て経験を通じて、「市内の保育所の情報が見つけづらい」と感じたことがきっかけで開発を始めました。


使用技術と構成について

フロントエンド

  • Nuxt 3
  • Tailwind CSS
  • Pinia(状態管理)

バックエンド

  • MongoDB Atlas
  • Mongoose(ODM)

その他

  • ホスティング:Vercel

1. MongoDB のスキーマ設計

つくば市が提供している保育施設に関するオープンデータをベースに、柔軟かつ拡張性のあるスキーマを設計しました。

  • MongoDB を選定した理由

    • オープンデータのフォーマットは将来的に変更される可能性があるため、柔軟に構造を変更できるドキュメント型 DB(MongoDB)を選択しました
    • 初期段階ではリレーションが少なく、スキーマの自由度を重視
  • 検索性を高める工夫

    • 「市区町村」「地区」などを住所から分割して個別にフィールド化
    • 区分(classification)として「私立」「民間」の 2 種を保持し、フィルタリングを容易に
    • 種別(type)には「保育所」「認定こども園」「小規模保育事業所」などを登録
const NurserySchema = new Schema<INurseryDocument>({
  classification: { type: String, required: true },
  type: { type: String, required: true },
  name: { type: String, required: true },
  prefecture: { type: String, required: true },
  city: { type: String, required: true },
  district: { type: String, required: true },
  ...
})

ポイント:データ型は INursery に切り出して共通管理し、保守性と型安全を意識しています。


2. Nuxt 3 での構築のポイント

Vue 3 の経験を活かして、よりスケーラブルな構成を目指し Nuxt 3 を採用しました。

  • Nuxt 3 を選定した理由

    • ページ構成や API 連携が統一されており、中〜大規模開発に向いている
    • SSG/SSR にも対応しており、将来的な SEO 対策にも対応可能
  • データ取得の工夫

    • 地域ごとの施設情報には useAsyncDatauseFetch を組み合わせて型付きで取得
export const useDistrictNurseries = (district: string) => {
  return useAsyncData<INursery[] | null>(`nurseries-${district}`, async () => {
    const { data } = await useFetch<INursery[]>(`/api/nurseries/${district}`);
    return data.value ?? null;
  });
};
  • 問い合わせの reCAPTCHA 対策
    • Google reCAPTCHA v3 のスコアチェックを $fetch で実装
const recaptchaRes = await $fetch<{ success: boolean; score: number }>(
  "https://www.google.com/recaptcha/api/siteverify",
  {
    method: "POST",
    body: new URLSearchParams({
      secret: process.env.GOOGLE_RECAPTCHA_SECRET_KEY as string,
      response: recaptchaToken,
    }),
  }
);
  • 型安全と自動 import の快適さ
    • TypeScript で API レスポンスや型定義を明確に
    • useAsyncDatauseRoute などは自動 import されるため、開発効率も大幅アップ

3. UI/UX まわりの工夫

モバイルでの利用を強く意識し、Tailwind CSS でスマホファーストな UI を設計しました。

  • 再利用性の高いコンポーネント設計
  • パンくずリストやカード表示による一覧性の向上

トップページ
トップページ

一覧ページ
一覧ページ

地域別ページ
地域別ページ

詳細ページ
詳細ページ

ポイント:「迷わず使える」+「情報に自然にたどり着ける」UI を目指しています。


4. 公開〜運用の流れ

  • Vercel による自動デプロイ

    • GitHub 連携のみで完結。Nuxt 3 との相性も抜群
  • データ投入は手動

    • 現状は CSV を元に手動で MongoDB に登録
    • 今後は自動化予定
  • フォームには reCAPTCHA v3 を導入

    • スパム対策も含めて安定運用中
  • 保守の負担はほぼゼロ

    • Vercel と MongoDB Atlas の組み合わせで、インフラコストも実質無料で安定

システム構成図

以下は、このアプリの全体構成です。
システム構成図

フロント・API・DB・外部連携をなるべくシンプルに構成し、個人でも運用可能な形を目指しました。


5. 今後やりたいこと

  • データ取り込みの自動化(CSV → MongoDB)
  • 管理画面の実装(非エンジニアでも保守できる設計)
  • 口コミ投稿機能(承認制のコメント投稿)
  • 地図検索やフィルターの強化
  • UI の操作性改善(片手操作など、よりスマホに優しい UI)

目指すところ:地域の保育情報が、誰でも簡単に、安心して探せる世界。


6. まとめ

子育ての中で感じた課題をもとに、「じゃあ自分で作ってみよう」と思ったのがこのプロジェクトの出発点でした。

今回はそこまで大規模な開発ではありませんが、誰かの役に立つものを自分で考え、作って、動かすという一連の体験は非常に価値あるものでした。

この記事が、「自分の課題感から何か作ってみたい」と思っている方のヒントや後押しになれば嬉しいです。


📌 サイト URL:https://kosodate-portal.coolat.net
🧑‍💻 GitHub:https://github.com/RyoheiTanaka

Discussion