買う理由が値段なら買わない、買わない理由が値段なら買う
これは自分が子供の頃から意識している考え方。最初に出会ったのはどこかの掲示板だったと思う。
持っているお金の量は変えられないが、その使い方で効用は大きく変えることができる。どうすれば効用を最大にできるかを考えることはとても大事。
自分の人生で軸にしている考え方はなんですか?と聞かれたらこれかもしれない。
この考え方の素晴らしいところは、お金を使うことも肯定していることだと思う。自分はむしろお金は使うべきだと考えていて、
DIE WITH ZEROの考え方のように、経験は積極的にお金を払っているつもりだし、これからもそうしていきたい。
買おうとしている対象の本当の価値みたいなものに目を向けて、それが欲しいものなのかどうかを考える姿勢は、お金に限らず仕事にも応用が効きそうな気がしている。
その仕事をする理由が「時間があるから」なら、その仕事はしないほうがいいだろうし、その仕事をしない理由が「忙しいから」なら、その仕事はしたほうがいいと思う。
Next.js(Vercel) + Rails + Auth0を使ってログイン機能を作る
Next.js(Vercel)でフロントエンド、Railsでバックエンドを用意する。結構やることが多かったのでメモ。
大きな流れ
なかなか全体像がつかみにくかった。今回取り組んでわかったことをまとめる。
ユーザーはNextからログインや登録を行い、Auth0に遷移する。
Auth0に遷移し、そこで認証を行う。認証が成功するとアクセストークンがJWTとして取得できるようになる
Next側でそのJWTを使ってRailsに情報を連携する
Rails側でJWTをパースし、問題なかったら処理を実行する
こういうことを行うためにこれから色々設定をする。
アプリケーションを作る
Reguler Web Applicationsを選択。アプリケーションを作ると、QuickStartでフレームワークごとの設定が案内されるので、原則そらのドキュメントに従う。
コールバックの設定
ローカル用と、本番のそれぞれを入力する。後述するSDKを用いればそのあたりのエンドポイントは勝手に作られる。
Next.js側の設定
Auth0 Next.js SDKをインストール
npm install @auth0/nextjs-auth0
dotenvで環境変数を設定する
どう設定すれば良いのかはドキュメントに記載されてる。
SDK Clientを作る
サンプルをベースに少し改造
// lib/auth0.js
import { Auth0Client } from "@auth0/nextjs-auth0/server";
export const auth0 = new Auth0Client({
domain: process.env.AUTH0_DOMAIN,
clientId: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
appBaseUrl: process.env.APP_BASE_URL,
secret: process.env.AUTH0_SECRET,
authorizationParameters: {
scope: process.env.AUTH0_SCOPE,
audience: process.env.AUTH0_AUDIENCE,
}
async onCallback(error, context, session) {ユーザー作成の処理}
});
Middlewareの作成
このサンプルもドキュメントから。
import type { NextRequest } from "next/server";
import { auth0 } from "./lib/auth0";
export async function middleware(request: NextRequest) {
return await auth0.middleware(request);
}
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
],
};
ここまででログインやログアウトのエンドポイントが作られる。
ログインボタンの設置
<a href="/auth/login">ログイン/新規登録</a>
ここでLinkなどを使うと先読みが入ってややこしくなるらしい。
Vercel側の設定
環境変数を設定する
設定した環境変数
最初環境変数の設定をミスっていてローカルでは問題ないのに本番でMIDDLEWARE_INVOCATION_FAILEDエラーが発生して詰まっていた。
Railsとの連携
Auth0APIの作成
Auth0のダッシュボードで作成。
Identifierと、ドメインの情報を記録する。これをRailsの設定に使う。
jwt gemの追加
Identifierと、ドメインの情報をクレデンシャルに追加
EDITOR="vim" bundle exec rails credentials:edit --environment development
auth0:
api_identifier: xxx
domain: xxx
ここでのdomainはhttps://を含まない
JWTの検証をするクラスを作成
このあたりもドキュメントのママ
# app/lib/json_web_token.rb
require 'net/http'
require 'uri'
class JsonWebToken
def self.verify(token)
JWT.decode(token, nil,
true, # Verify the signature of this token
algorithm: 'RS256',
iss: "https://#{Rails.application.credentials.auth0[:domain]}/",
verify_iss: true,
aud: Rails.application.credentials.auth0[:api_identifier],
verify_aud: true) do |header|
jwks_hash[header['kid']]
end
end
def self.jwks_hash
jwks_raw = Net::HTTP.get URI("https://#{Rails.application.credentials.auth0[:domain]}/.well-known/jwks.json")
jwks_keys = Array(JSON.parse(jwks_raw)['keys'])
Hash[
jwks_keys
.map do |k|
[
k['kid'],
OpenSSL::X509::Certificate.new(
Base64.decode64(k['x5c'].first)
).public_key
]
end
]
end
end
認証周りのサービスクラスを作成
TokenVerificationを作り、認証してユーザーを返すAuthorizationServiceと、新規にユーザーを作成するUserRegistrationServiceを作る
module TokenVerification
private
def http_token
if @headers["Authorization"].present?
@headers["Authorization"].split(" ").last
end
end
def verify_token
JsonWebToken.verify(http_token)
end
end
class AuthenticationService
include TokenVerification
def initialize(headers = {})
@headers = headers
end
def perform!
payload, _header = verify_token
User.find_by!(sub: payload["sub"])
end
end
class UserRegistrationService
include TokenVerification
def initialize(headers = {})
@headers = headers
end
def perform!
payload, _header = verify_token
User.find_or_create_by(sub: payload["sub"])
end
end
認証用のコントローラーの作成
認証に成功したらユーザーを返す
class SecuredController < ApplicationController
before_action :authorize_request
private
def authorize_request
@current_user = AuthenticationService.new(request.headers).perform!
rescue JWT::VerificationError, JWT::DecodeError
render json: { errors: [ "Not Authenticated" ] }, status: :unauthorized
end
def current_user
@current_user
end
end
ユーザーの作成はUsersControllerに作成
class UsersController < SecuredController
skip_before_action :authorize_request, only: [ :create ]
def create
user = UserRegistrationService.new(request.headers).perform!
if user.save
render json: user, status: :created
else
render json: { errors: user.errors.full_messages }, status: :unprocessable_entity
end
end
end
これでログインまわりの機能ができた
Renderのアプリからsupabaseの無料枠DBを利用する
ちょっと作りたいアプリが出来たが、データベースに課金するほどのアプリでもない。
Renderの無料枠とsupabaseの無料枠のDBを使って、インフラコストゼロでちょっとしたサービスを作る。
database.ymlの設定
production:
primary: &primary_production
<<: *default
host: <%= ENV["APP_DATABASE_HOST"] %>
username: <%= ENV["APP_DATABASE_USER"] %>
password: <%= ENV["APP_DATABASE_PASSWORD"] %>
Renderの設定
環境変数を設定する。設定した項目は以下。設定値はsupabaseから閲覧できる。
デプロイしようとしたところNetwork is unreachable (ActiveRecord::ConnectionNotEstablished)が発生。エラーメッセージ的にIPv6で接続をしているようで、Session poolerの情報で接続を試みると成功

無料枠で2つのプロジェクトまで作成できるので、今動かしている個人開発のデータ移行をしても良いのかも?
フルリモートが急にしんどくなった
フルリモートの会社に1年半ほど務めている。
今の会社はフルリモートの中でも究極だと思う。朝会が毎日5~10分あるだけで、それ以外は一切会議がない。全てテキストコミュニケーション。リモートワークと仕事の効率に関する話がよく出てくるが、少なくとも今の会社においてはこのスタイルは一番効率的だと考えている。
フルリモートを始めてから最初の1年ほどはフルリモート最強という気持ちでいっぱいだったし、これを今後もずっと続けていくのだと考えていた。ただ、ここ1,2ヶ月ほどで急にフルリモートがしんどくなってしまった。仕事においてはしんどさは特に感じていない。感じているのは個人の生き方としての部分。
元からフルリモートワークに対する違和感のような物があった。ありきたりだが、社会性が失われていく感覚が強かった。自分はよくこの違和感を人に伝えるときに、「老後」という表現を使っている。決して老後にネガティブな意味を持たせているわけではない。30代に似合わない時間の使い方をしているという意味で老後という言葉を選んでいる。
リモートワークでかつ裁量労働だと好きな時間に仕事ができるし、好きな時間に休憩することも出来る。横になることもよくある。ストレスがなく、すごく自由で、それはとても魅力的なことなのだが、家で一人で仕事をしたり横になったりを繰り返していると、だんだん仕事が仕事に感じられなくなる。もちろん仕事はちゃんとしているし、成果も出しているのだが、メリハリがないというか、ずっと休日を過ごしている気持ちになる。
「ずっと休日」の字面だけ見るとそれは良いことのように見えるかもしれないが、なんとも言えないしんどさがある。休みの日と普段の日の違いが薄くなり、日々の濃淡がだんだん薄くなってくる。よく聞く「会社と家を往復するだけの毎日」みたいな愚痴、あれの範囲が極端に狭くなった状態になる。
自分の活動範囲がどんどん小さくなっていくのも感じる。全ての用事が家から出発しなければならないことが原因として大きいと思う。「ちょっと気になる場所やイベントがあるけど、家から行くほどのものでもない」ようなものがいくつかある。そういうものは家にいると億劫になって諦めてしまう。これが通勤をしていると「帰りに寄ってみよう」ができる。昔はいろいろなものに顔を出すタイプの人だったが、最近はずっと家にいる気がする。ずっと家にいると不思議なもので、何か新しいことを始める気持ちもだんだん減ってくる。
今でもボルダリングは定期的に行っているし、土日は基本出かけているため、外出自体はしている。また、同棲をしているので日常的に会話はできている。しかし、ずっと家にいると「今日こんな事があったよ」みたいな出来事が特にない。事件がない。日常が全て自分の意思で起こしたものだけになり、外乱のような偶発的事象がない。これは自由とも平穏とも気楽とも呼べるが、自分からしたら退屈になってしまった。
最近子どもがほしいのかも?などと考えていたが、よくよく考えると自分は外乱がほしいだけのような気がしてきた。子育ての大変さは知人の話から強く感じている。生半可に手を出してはいけない気持ちがある。
従来の仕事や職場というものは、こういう外乱の固まりで、無意識のうちにそれらを享受していたんだなと感じる。
もちろんフルリモートを悪者にしたいわけではない。今の環境が特殊すぎるのかもしれない。もしかしたら雑談タイム的なものを組織が用意したら解決するのかもしれない。ただ、フルリモートでない環境に移るのが手っ取り早いというところが実際にある。
一年前はフルリモート最強という考え方を持っていたので、時間とともに自分の考え方が大きく変わってしまったことを実感している。こういうふうにブログに残しているのは今の考えのスナップショットを残し、将来どんな考え方に変わっているのか再確認できたら良いなという思惑がある。
ちなみに、縁もあり、7月から新しい会社で働く。今度はハイブリッドの環境。今度はどんな考え方になるのか自分でも気になる。もしかしたら「やっぱりフルリモート最強」と言っているかもしれない
Claude Codeを0.42ドルで試したメモ
Claude4からIDEサポートされたらしい。そろそろ触るタイミングが来た感じ。触る
導入
npm install -g @anthropic-ai/claude-code
VSCode開いてClaude Codeを起動
コンソールでの差分表記のスタイルを聞かれるけど、なんでも良いのでデフォルトを選択

ログイン方法を選択する。定額課金かAPIの従量課金か選択する。まずはお試しなので従量課金を選んでみる。

クレジットを5ドル買ってねと言われる。払うぞ

セッティング周りは一旦デフォルトで

使ってみる
お題としてこのブログのヘッダーに自分のソーシャルアカウントのリンクを張りたいことを伝える。
そうすると、どういう道のりでタスクを完了する予定なのか示してくれる。Clineもそういう進め方をするけど、Claude Codeの方が見やすいかも。
どういうライブラリを使っているのかとか、そういう背景を考慮してコードを書いてくれる。

作業のステップごとに確認してくる。これは飛ばすことも出来るけど今は一個ずつ確認。
ほぼお任せでやりたいことができた
最終的に$0.42かかりました。
感想
あまり難しいタスクをお願いしていないので評価するのも難しいのですが、これぐらいのタスクだったらCline + Deepseekでも良いかなとも思いました。
ただこっちのほうが全体のコンテキストを理解して進めてくれる感覚がありました。Clineだと1ファイルずつ読み取りを行ったりする関係上、全体を考慮したことが苦手そうな雰囲気がある。
このあたりはこれから色々試してみようかなと思います。そのうち定額制に入るかもしれません。