🚀

Next.js、Vercel、supabaseで手っ取り早く無料でサービスを作る

🔄

モダンなWebサービスを作りたいけど、できるだけお金をかけたくない。そんな方におすすめなのが、Next.js + Vercel + Supabaseの組み合わせです。この3つのツールを使えば、完全無料でフルスタックのWebアプリケーションを構築できます。

なぜこの組み合わせが最強なのか

無料枠が充実している

  • Next.js: フロントエンドフレームワーク(無料)
  • Vercel: ホスティング・デプロイ(Hobbyプランは無料)
  • Supabase: データベース・認証・リアルタイム機能(無料枠あり)

開発効率が良い

  • Next.jsの豊富な機能(SSR、API Routes、最適化)
  • Vercelの自動デプロイ
  • Supabaseの即座に使えるバックエンド機能

実際の構築手順

ステップ1: Next.jsプロジェクトの作成

まずはNext.jsプロジェクトを作成しましょう。

npx create-next-app@latest my-app
cd my-app

TypeScriptを使う場合(推奨):

npx create-next-app@latest my-app --typescript
cd my-app

ステップ2: Supabaseの設定

Supabaseプロジェクトの作成

  1. Supabaseにアクセス
  2. GitHubアカウントでサインアップ
  3. 「New project」をクリック
  4. プロジェクト名とパスワードを設定
  5. リージョンを選択(日本の場合はNortheast Asia (Tokyo)推奨)

環境変数の設定

プロジェクト作成後、Supabaseの管理画面で以下の情報を取得:

# .env.local
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key

Supabaseクライアントのインストール

npm install @supabase/supabase-js

Supabaseクライアントの設定

// lib/supabase.js
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY

export const supabase = createClient(supabaseUrl, supabaseAnonKey)

ステップ3: データベースのテーブル作成

Supabaseの管理画面のSQL Editorで以下を実行:

-- ユーザープロフィールテーブル
create table profiles (
  id uuid references auth.users on delete cascade,
  updated_at timestamp with time zone,
  username text unique,
  full_name text,
  avatar_url text,
  website text,

  primary key (id),
  unique(username),
  constraint username_length check (char_length(username) >= 3)
);

-- RLS (Row Level Security) を有効化
alter table profiles enable row level security;

-- ポリシーの設定
create policy "Public profiles are viewable by everyone."
  on profiles for select
  using ( true );

create policy "Users can insert their own profile."
  on profiles for insert
  with check ( auth.uid() = id );

create policy "Users can update own profile."
  on profiles for update
  using ( auth.uid() = id );

ステップ4: 認証機能の実装

認証コンポーネントの作成

// components/Auth.jsx
import { useState } from 'react'
import { supabase } from '../lib/supabase'

export default function Auth() {
  const [loading, setLoading] = useState(false)
  const [email, setEmail] = useState('')

  const handleLogin = async (email) => {
    try {
      setLoading(true)
      const { error } = await supabase.auth.signInWithOtp({ email })
      if (error) throw error
      alert('Check your email for the login link!')
    } catch (error) {
      alert(error.error_description || error.message)
    } finally {
      setLoading(false)
    }
  }

  return (
    <div className="row flex flex-center">
      <div className="col-6 form-widget">
        <h1 className="header">Supabase + Next.js</h1>
        <p className="description">Sign in via magic link with your email below</p>
        <div>
          <input
            className="inputField"
            type="email"
            placeholder="Your email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          />
        </div>
        <div>
          <button
            onClick={(e) => {
              e.preventDefault()
              handleLogin(email)
            }}
            className="button block"
            disabled={loading}
          >
            {loading ? <span>Loading</span> : <span>Send magic link</span>}
          </button>
        </div>
      </div>
    </div>
  )
}

メインアプリケーションの実装

// pages/index.js
import { useState, useEffect } from 'react'
import { supabase } from '../lib/supabase'
import Auth from '../components/Auth'
import Account from '../components/Account'

export default function Home() {
  const [session, setSession] = useState(null)

  useEffect(() => {
    supabase.auth.getSession().then(({ data: { session } }) => {
      setSession(session)
    })

    supabase.auth.onAuthStateChange((_event, session) => {
      setSession(session)
    })
  }, [])

  return (
    <div className="container" style={{ padding: '50px 0 100px 0' }}>
      {!session ? <Auth /> : <Account key={session.user.id} session={session} />}
    </div>
  )
}

ステップ5: Vercelへのデプロイ

GitHubリポジトリの作成

  1. GitHubで新しいリポジトリを作成
  2. ローカルのプロジェクトをpush
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/yourusername/your-repo.git
git push -u origin main

Vercelでのデプロイ設定

  1. Vercelにアクセス
  2. GitHubアカウントでサインアップ
  3. 「New Project」をクリック
  4. GitHubリポジトリを選択
  5. 環境変数を設定:
    • NEXT_PUBLIC_SUPABASE_URL
    • NEXT_PUBLIC_SUPABASE_ANON_KEY
  6. 「Deploy」をクリック

実践的なTips

1. 環境変数の管理

開発環境と本番環境で異なる設定が必要な場合:

# .env.local (開発用)
NEXT_PUBLIC_SUPABASE_URL=your-dev-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-dev-supabase-anon-key

# .env.production (本番用)
NEXT_PUBLIC_SUPABASE_URL=your-prod-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-prod-supabase-anon-key

2. パフォーマンス最適化

Next.jsの画像最適化を活用:

import Image from 'next/image'

function ProfileImage({ src, alt }) {
  return (
    <Image
      src={src}
      alt={alt}
      width={200}
      height={200}
      priority
    />
  )
}

3. SEO対策

Next.jsのHeadコンポーネントを使用:

import Head from 'next/head'

function MyPage() {
  return (
    <>
      <Head>
        <title>My App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        {/* コンテンツ */}
      </main>
    </>
  )
}

4. エラーハンドリング

Supabaseのエラーを適切に処理:

const handleSubmit = async (formData) => {
  try {
    const { data, error } = await supabase
      .from('your_table')
      .insert(formData)
    
    if (error) throw error
    
    // 成功時の処理
    console.log('Data inserted:', data)
  } catch (error) {
    console.error('Error:', error.message)
    // ユーザーにエラーメッセージを表示
  }
}

無料枠の制限と対策

Vercel Hobbyプランの制限

  • 月間100GBの帯域幅
  • 月間100回のサーバーレス実行
  • カスタムドメインは1つまで

Supabase無料枠の制限

  • 2つのプロジェクトまで
  • 500MBのデータベースストレージ
  • 月間50,000回のAPI呼び出し

スケールアップ時の対策

サービスが成長したら段階的に有料プランに移行:

  1. まずはVercelのProプラン(月$20)
  2. SupabaseのProプラン(月$25)
  3. 必要に応じてカスタムプラン

まとめ

Next.js + Vercel + Supabaseの組み合わせなら、初期費用ゼロでモダンなWebサービスを構築できます。特に以下のような場面で威力を発揮します:

  • MVP(最小実行可能製品)の開発
  • 個人プロジェクト
  • プロトタイプの作成
  • 小規模なビジネスアプリ

まずは小さく始めて、成長に合わせて段階的にスケールアップしていく戦略が取れるのが最大の魅力です。

今すぐ始めてみましょう!