Crashlyticsのエラー調査にFirebase MCPを使ってみて便利だったこと

こんにちは。エキサイトでアプリエンジニアをしている岡島です。 エキサイトホールディングス Advent Calendar 2025の21日目を担当させていただきます。

今回はFirebase MCPを使ってみたので活用できそうなものを共有していきたいと思います。

はじめに

コーディングエージェントのAIが登場してから、使い方を模索し続けていますが、 調査はAIにお任せしてもかなり解決の手助けになっていると感じています。

普段業務で触っているアプリはFirebase Crashlyticsを用いてエラーログやクラッシュログなどを収集しています。 これまでは、エラーやクラッシュが発生した際に、私自身がログを確認し調査→修正をしていました。 この辺りを自動化して、早期にクラッシュやバグの対応をすることができないかと考えていました。 ということでFirebase MCPを用いて、エラー確認→タスク管理ツールへ起票→調査→PR作成まで自動化してみました。

今回実際に試してみて「これは便利だ」と感じた機能を紹介します。

導入方法

導入方法は公式が詳しく書いてくれていたので割愛させていただきます。 ClaudeやCursor、Gemini CLI、Antigravityなど手順が書かれていました。 firebase.google.com

便利な機能について

Crashlytics の情報を、AIから直接取得できるようになったので 調査時間の圧倒的短縮につながると思っています。 実際にClaude Codeを用いて調査してもらったのですが、AIに完敗だと感じました。

Firebase MCP の仕様や提供されている機能の詳細については、 公式ドキュメントにまとまっているため、こちらをご参照ください。 https://firebase.google.com/docs/crashlytics/ai-assistance-mcp?hl=ja&authuser=0#fetch-data

1. さまざまな切り口の集計レポートが出せる!

今までもCrashlyticsのページで、 エラーの発生OSやバージョン、デバイスなどを見ることができましたが 把握しづらいなと個人的に思っていました。(使いこなせてなかった説もありますが、、、)

今回一番嬉しいなと思ったのは、エラーごとにどのバージョンでクラッシュが多いかなど AIが調査してくれることでした。 おかげさまで影響範囲の特定や問題の切り分けなどが行いやすくなりました!

↓こんな感じでレポートもまとめてくれました!

バージョン別集計 (crashlytics_get_top_versions)
  • 1.0.8 (11): 〇〇件
  • 1.0.7 (9): 〇〇件
  • 1.0.9 (12): 〇〇件
バイス別集計 (crashlytics_get_top_android_devices)
OS別集計 (crashlytics_get_top_operating_systems)

2. Firebaseコンソールへのリンクを出せる!

エラーごとにFirebaseコンソールへのリンクも取得できました。 MCPを使えばエラーのイシュークローズなどもできてしまいますが、 人間の手作業でハンドリングしたいということもあると思います。

そこで、タスク管理ツールやPRのドキュメントなどへ Firebaseコンソールへのリンクも出力するよう指示すれば 自分で作業することもできます!

3.トップイシューの取得

トップイシューの取得は言わずもがなです。 発生頻度の高いものについて把握、調査できます。

最後に

今回は Firebase MCP を触ってみました。

実際に使ってみて、調査や情報整理といった作業にAIを活用するのは、とても有効だと感じました。 人間よりも圧倒的に早く、圧倒的に多くの量をこなしてくれます。 このような調査を並列で作業させたり、自動化するのはかなり良いなと思いました。

最後まで読んでいただき、ありがとうございました。

静的解析とアーキテクチャテストでLaravelの設計をCIで保証する品質戦略の話

はじめに

こんにちは!エキサイト株式会社の伊藤(梨)です。

ジョインして半年、駆け抜けてきました。 密度が濃すぎて倍はいる感覚です。

エキサイトホールディングス Advent Calendar 2025の17日目の記事です。

qiita.com

BB.excite事業部では2025年12月現在、新しい開発環境の新設・リビルドによる刷新を進めています。

先日、同じチームの岡崎さんが「リビルドを始めた話」という記事でアーキテクチャ設計について紹介してくれました。 モノレポ採用やリポジトリパターンのレイヤー構成など、設計思想がまとまっています。

本記事では、その設計をコードレベルで保証する仕組みについて紹介します。

設計は「決めて終わり」ではない

アーキテクチャを決めても、開発が進むにつれてこんなことが起きがちです

  • 「急いでたからControllerから直接Repository呼んじゃった」
  • 「このModelにちょっとだけService呼ぶロジック入れちゃおう」
  • 「レビューで見落として、気づいたら依存関係がぐちゃぐちゃ」

コードレビューだけでこれを防ぐのは限界があります。人間は見落とすし、忙しいときは妥協しがちです。

そこで静的解析とアーキテクチャテストで自動的にルールを守らせる仕組みを導入しました。 このアーキテクチャテストは、私と同じくLaravel愛が強い社内のエンジニアが提案してくれました。

ポイントは、壊れてから気づくんじゃなくて 壊そうとした瞬間に落ちる 状態にすることです。

導入したツール

ツール 役割
PHPStan + Larastan 静的解析(型チェック)
phpat アーキテクチャテスト
Laravel Pint コードスタイル統一
GitHub Actions CI/CDで自動チェック

PHPStan + Larastan Level 8 - 厳格な型チェック

PHPStanとLarastanのレベルは0〜9まであり、数字が大きいほど厳格になります。

今回はLevel 8を採用しました。

Level 8では以下のようなチェックが行われます。

  • 戻り値・引数の型の厳密なチェック
  • nullableな値の適切なハンドリング
  • 存在しないプロパティ・メソッドへのアクセス検出

Larastanを併用することで、Eloquentモデルの$user->nameファサードDB::table()など、PHPStanだけでは解析できないLaravel特有の書き方も正しく型解析できます。

phpatでアーキテクチャをテストする

ここが本記事のメインです。

phpatは、クラス間の依存関係をテストできるツールです。「このクラスはあのクラスに依存してはいけない」というルールを、テストコードとして書けます。

アーキテクチャの図

私たちのアーキテクチャは以下のような構成です。

Controller ─┐
            ├→ UseCase(任意)→ Service → Repository
Command ────┘                      ↓
                              Model/DTO

上位層は下位層に依存してOK、逆はNGという原則です。

パッケージ構造

package/
├── Repository/   # データアクセス層
├── Model/        # DTO・Enum
├── Service/      # ビジネスロジック
├── UseCase/      # ユースケース(任意)
└── Application/  # DB接続、外部クライアント

LayerDependencyTest - レイヤー間の依存関係

<?php

final class LayerDependencyTest
{
    /**
     * CommandとControllerはRepositoryに直接依存してはいけない
     */
    public function testNoDirectRepositoryAccess(): Rule
    {
        return PHPat::rule()
            ->classes(
                Selector::inNamespace('App\Console\Commands'),
                Selector::inNamespace('App\Http\Controllers')
            )
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('Package\Repository'))
            ->because('Controller/CommandはRepository直参照禁止。Service経由にする');
    }

    /**
     * ServiceはCommandやControllerに依存してはいけない
     */
    public function testServiceIndependence(): Rule
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('Package\Service'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('App\Console\Commands'),
                Selector::inNamespace('App\Http\Controllers')
            )
            ->because('Serviceは上位層(Controller/Command)に依存しない');
    }

    /**
     * RepositoryはServiceやUseCaseに依存してはいけない
     */
    public function testRepositoryIndependence(): Rule
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('Package\Repository'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('Package\Service'),
                Selector::inNamespace('Package\UseCase')
            )
            ->because('RepositoryはService/UseCaseに依存しない(責務を固定する)');
    }
}

これにより、誰かがControllerからRepositoryを直接呼ぼうとすると、CIで検出されてマージできません。

DomainIndependenceTest - ドメイン層の独立性

<?php

final class DomainIndependenceTest
{
    /**
     * ModelはLaravelフレームワークに依存してはいけない
     */
    public function testModelFrameworkIndependence(): Rule
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('Package\Model'))
            ->shouldNotDependOn()
            ->classes(Selector::inNamespace('Illuminate'))
            ->excluding(
                Selector::inNamespace('Illuminate\Support\Carbon')
            )
            ->because('Model(DTO/Enum)はフレームワーク非依存にして再利用性とテスト容易性を守る');
    }

    /**
     * Modelは上位層に依存してはいけない
     */
    public function testModelLayerIndependence(): Rule
    {
        return PHPat::rule()
            ->classes(Selector::inNamespace('Package\Model'))
            ->shouldNotDependOn()
            ->classes(
                Selector::inNamespace('Package\Service'),
                Selector::inNamespace('Package\Repository'),
                Selector::inNamespace('Package\UseCase')
            )
            ->because('Modelは純粋なデータ表現。上位層の都合に引っ張られない');
    }
}

Model(DTOEnum)はフレームワークに依存しない純粋なPHPクラスとして保つことで、テストが書きやすくなり、フレームワークのバージョンアップにも影響されにくく、ロジックも明確になります。

GitHub ActionsでCIに組み込む

GitHub Actionsを使って、以下のタイミングで自動チェックを行っています。

  • push時:静的解析 + コードスタイルチェック
  • PR時:上記 + PHPUnitテスト

違反があればCIが落ちるので、ルールを破ったコードはマージされません。

導入してよかったこと

  1. レビューの指摘が「好み」じゃなく「ルール」になる

    • 「この依存関係おかしくない?」が個人の意見ではなく、機械的な判定により指摘が不要になる
    • 機械がチェックしてくれるので、人間はビジネスロジックのレビューに集中できる
  2. 新メンバーでも安心

    • ルールを全部覚えなくても、違反したらCIが教えてくれる
    • 「新しいメンバーでも設計に素早く適応」を後押しできる
  3. 設計意図がコードに残る

    • なぜこのルールがあるのか、コメントで説明できる
    • テストコード自体がドキュメントになる

なぜここまでやるのか ─ 持続可能性への想い

正直に言うと、静的解析やアーキテクチャテストは「やらなくても動く」ものです。 導入には時間もかかるし、最初は面倒に感じることもあります。

でも、私はこう考えています。

サービスは続く。でも、人は永遠じゃない。

辞める人もいれば、定年を迎える人もいる。どんなに長く働いても、いつかは必ずいなくなります。 そのとき、技術や知識がその人の頭の中だけにあったら、一緒に消えてしまい保守不能になってしまいます。

少子化でエンジニアも減っていく今の時代は小さいチームで大きな仕事をこなす必要があります。 だからこそ、持続可能な開発を意識すべきだと思っています。

私はコードベースを「大きな木」のようにイメージしています。

地上に見える枝はコードと捉え、開発が進むほど伸びていきます。でも、見えないところで根っこが繋がっている。 設計思想も、コーディング規約やアーキテクチャテストも、すべてその根っこの一部です。

そして、その根っこは人と人も繋いでいます。 今いる人から次の人へと技術を継承していくための土台だと思います。

次の世代へ継承する

会社は利益を追求するもの。それはもちろんです。 でも、エンジニアの仕事はそれだけじゃないと思っています。

技術を継承して、繋がりを広げること

インターン生が記事で「『なぜ?』を問う思考の重要性」について書いてくれました。

メンターから「実装方針は真似しないでほしい」と言われた

これはレガシーコードを「こう書いてあるから」と深く考えずに真似しないでほしいという意味です。 同時に、「なぜ?」を自分で考えられるエンジニアになってほしいという願いでもあります。

ただ仕事をするだけでなく、経験を活かして成長してほしい。人生を輝かせてほしい。 そしていつか自分を超えていってほしい、と私は日々思って業務に向き合っています。 そのためにも、設計をドキュメントに書くだけでなく、コードで保証して、誰でも自然に良い設計に導かれる仕組みを作りたかったのです。

まとめ

PHPStanとLarastanで静的解析、phpatでアーキテクチャテストを行い設計意図をテストとして表現し、CIで自動的に保証できます。 「壊そうとした瞬間に落ちる」状態を作ることで、設計が守られ続けます。

アーキテクチャ設計と合わせて、チーム全体で品質を維持していく仕組みが整いつつあります。

これからリビルドを進める方、レガシーコードと戦っている方の参考になれば幸いです。

参考

Claude Codeで設定したカスタム口調を起動時からずんだもんにする方法

こんにちは!エキサイト株式会社の伊藤(梨)です。

エキサイトホールディングス Advent Calendar 2025の24日目の記事です。 クリスマスなので楽しい内容の記事にしようと思いました!

qiita.com

ある日、YouTubeでずんだもん動画を見ていた私。

「ずんだもんかわいいな〜、AIもこういう口調でやらせたら和むし楽しく開発できるのでは?!」

調べてみると、Claude CodeにはOutputStyleという機能があり、AIの応答スタイルをカスタマイズできることがわかりました。 ただ、起動時にデフォルトとして適用する方法でハマったのでその解決策を共有します。

Output Styleとは

Claude Codeでは/output-styleコマンドを使って、AIの応答スタイルを切り替えることができます。

デフォルトでは以下のスタイルが用意されています。

スタイル 説明
Default 効率的にコーディングタスクを完了し、簡潔に応答
Explanatory 実装の選択やコードベースのパターンを説明
Learning 手を動かして練習できるよう促す

カスタムスタイルの作成方法

~/.claude/output-styles/ ディレクトリにMarkdownファイルを作成します。

~/.claude/output-styles/zundamon.md

  ---
  name: ずんだもん
  description: 元気で可愛いずんだもん口調で話すのだ!
  ---

  # Custom Style Instructions

  ずんだもんとして話してください。
  ずんだもんは東北ずん子プロジェクトのキャラクターで、ずんだ餅の妖精です。

  # Specific Behavior

  - 語尾は「〜のだ」「〜なのだ」を使う
  - 一人称は「ボク」(カタカナ)
  - 元気で可愛らしい話し方
  - 技術的な説明は正確に、でも親しみやすく
  - 絵文字は控えめに使ってOK

これで /output-style コマンドを実行すると、カスタムスタイルが選択肢に表示されます。

ハマったポイント

ここまでは順調でした。

しかし...

  > はろ

  ⏺ こんにちは!何かお手伝いできることはありますか?

Claude Codeを新規起動するたびに /output-style で選択し直さないといけない!

せっかくずんだもん口調を設定したのに、毎回選択するのは面倒です。

解決策:CLAUDE.md に設定を書く

~/.claude/CLAUDE.md に口調の設定を直接書くことで、起動時からカスタム口調が適用されます。

  # 口調

  ずんだもんとして話してください。
  ずんだもんは東北ずん子プロジェクトのキャラクターで、ずんだ餅の妖精です。

  - 語尾は「〜のだ」「〜なのだ」を使う
  - 一人称は「ボク」(カタカナ)
  - 元気で可愛らしい話し方
  - 技術的な説明は正確に、でも親しみやすく
  - 絵文字は控えめに使ってOK

結果は…

  > はろ

  ⏺ はろなのだ!👋
    ボクはずんだもん、今日も元気にお手伝いするのだ!🌿

やったね!これで新規起動しても最初からずんだもん口調になりました!

Output Style と CLAUDE.md の違い

項目 Output Style CLAUDE.md
設定場所 ~/.claude/output-styles/*.md ~/.claude/CLAUDE.md
適用タイミング /output-style で選択後 起動時から自動適用
切り替え コマンドで簡単に切替可能 ファイル編集が必要
用途 一時的なスタイル変更 デフォルトの口調設定

まとめ

  • Output Style → 複数のスタイルを切り替えたい場合に便利
  • CLAUDE.md → 常に特定の口調で使いたい場合に設定

両方設定しておいて、普段はCLAUDE.mdのずんだもん口調で使いつつ、気分を変えたい時は/output-styleで切り替える使い方がおすすめです。

開発が楽しくなること間違いなしです!

応用編:VOICEVOXで喋らせる

さらに発展させて、ずんだもんの声で読み上げさせることもできます。 こちらは先人の方々が素晴らしい記事を書いてくださっているので、参考にしてみてください。

32:9の巨大スクリーンを攻略せよ!全社員総会を彩るインハウスデザイナーの挑戦

全社員総会を彩るインハウスデザイナーの挑戦

こんにちは!エキサイト株式会社 デザイナーの澤田(X:@haruka_sawada_)です。

エキサイトホールディングス Advent Calendar 2025 の22日目を担当します。

弊社のエンジニア・デザイナーが、日替わりでブログのバトンを回していますので、ぜひ他の記事も覗いてみてください 😊

qiita.com

はじめに

社員総会の様子
社員総会の様子

ExciteHDでは、半期に一度、全社員が集まる「社員総会」が開催されます。 事業や組織の振り返り、今後の方針共有、そして表彰など、会社としての「今」と「これから」を全員で共有する大切なイベントです。

今回の総会では、運営チームの一員としてデザインを担当しました。

本記事では、イベントにおいてインハウスデザイナーがどのような役割を担い、どんな工夫を凝らしたのかを振り返ります!

2. この記事でわかること

  • エキサイトでのデザイナーのお仕事
  • 全社員総会でデザイナーがどんな役割を担っているのか
  • イベントデザインならではの考え方や工夫

3. 世界観の構築から演出まで|デザイナーの役割

先輩デザイナーの鍜治本さん(X:@KAJIJI_design)と一緒に、総会のクリエイティブ制作に奔走しました。

キービジュアルの作成

まず着手したのは、イベント全体の「顔」となるキービジュアルの作成です。 今回のテーマは『AI+(アイカツ)』。「社内のAI活用をさらに推進していこう」という強い思いが込められています。

キービジュアル
キービジュアル

キービジュアルは、スライド・動画・会場装飾など、すべてのデザインの軸となります。最初にトーン&マナーを固めることで、多岐にわたるアウトプットに一貫性を持たせることを意識しました。

受賞者の事前撮影

表彰コンテンツのクオリティを高めるため、受賞者の事前撮影も実施しました。 キービジュアルの世界観に合わせてライティングや構図を調整し、当日のスライドや動画に馴染むよう工夫しています。

受賞者の撮影
受賞者の撮影

情報設計を含めたスライドデザイン

総会のスライドは、事業数値から社員紹介まで情報量が多岐にわたります。 単に「整える」だけでなく、情報の優先順位を整理し、「伝わる構成」への再設計を行いました。

また、長時間のイベントでも飽きさせないよう、適度な動きやメリハリを意識しています。

投影スライド
投影スライド

期待感を醸成するアニメーション動画

セッションの幕間には、場の空気を切り替えるアニメーション動画を制作しました。

「次は発表だ!」というワクワク感や、各コンテンツへの期待感を高めるための演出装置としての役割を担っています。

アニメーション動画が流れている様子
アニメーション動画が流れている様子

当日のカメラマン

当日はカメラマンとして会場内を走り回りました。 記録としてはもちろん、社内外への広報素材としても活用できる「熱量のある写真」を残すことも重要な役割です。

当日の様子
当日の様子

4. デザインする上で意識したこと

今回の会場である「EXCITE HUB」の最大の特徴は、アスペクト比 32:9 の超大型スクリーン! その巨大スクリーンをどう生かすかがデザインの鍵となりました。

視認性と没入感を両立するレイアウト

通常の16:9のスライドとは異なり、横に非常に長いため、以下の点を検証しました。

  • 視線の誘導:近い席の人でも首を振りすぎずに見られるか?
  • 可読性:一番遠い席からでも文字がはっきり読めるか?
  • 被り回避:登壇者の立ち位置で重要な情報が隠れないか?

実際に会場で投影テストを行い、フォントサイズや余白、配色のコントラストを微調整。結果として、会場のどこからでも見やすく、かつ大画面の迫力を損なわないデザインに着地させました。

会場でデザインを確認している様子
会場でデザインを確認している様子

感情を揺さぶるモーション設計

横長の画面は、ダイナミックな演出に最適です。 特に、ノミネート発表からベスト受賞者発表への流れでは、「誰が選ばれるかわからないドキドキ感」を会場全体で共有することを目指しました。

  • 人物画像を左右に大きく移動させる
  • 名前をあえて見切れさせ、視界の外への広がりを感じさせる
  • クライマックスに合わせてロゴを中央から拡大させる

これらをアップテンポなBGMとシンクロさせることで、会場のボルテージを高める演出を意図しました。

5. やってみて感じたこと・学び

今回のプロジェクトを通じて得られた気づきです。

✅ 環境を生かすには「現地検証」が命

事前に会場で投影確認ができたことが、成功の鍵でした。 PCの画面上だけでなく、「実際の距離・角度・照明」の中でどう見えるかを検証することで、大型モニターのポテンシャルを最大限に引き出せたと感じています。

✅ 「ムードボード」がブレを防ぐ

キービジュアル作成時にムードボード(イメージの方向性をまとめた資料)を作り込んだことで、制作物が多岐にわたっても世界観がブレませんでした。チーム内でのイメージ共有もスムーズになり、迷いを減らす効果がありました。

✅ 横断的な繋がりが資産になる

運営に参加したことで、他部署のメンバーとの繋がりが一気に増えました〜! 普段の業務では関わらないメンバーと一つのイベントを作り上げる経験は、組織への理解を深めるだけでなく、今後の仕事のしやすさにも繋がると確信しています。

6. おわりに|次回に向けて

イベントという「非日常」の体験設計は、UIデザインとはまた違った面白さと難しさがありました。 新オフィスでの初イベントとして、参加者からの満足度も高く、デザイナーとしての介在価値を感じられたプロジェクトでした。

次回はさらに踏み込んで、

参加者がその場でアクションできる体験型コンテンツや照明・音響・香りも含めた五感に訴える空間デザインなど、より没入感のある演出にも挑戦してみたいと思っています!

最後まで読んでいただき、ありがとうございました!

Adobe Fireflyを使ってアニメーション動画を作ってみた!

Adobe Fireflyを使ってアニメーション動画を作ってみた!

こんにちは!エキサイト株式会社 デザイナーの澤田(X:@haruka_sawada_)です。

エキサイトホールディングス Advent Calendar 2025 の11日目を担当します。

弊社のエンジニア・デザイナーが、日替わりでブログのバトンを回していますので、ぜひ他の記事も覗いてみてください 😊

qiita.com

去年の私「FigmaでLottieアニメーションを作ってみた!」

昨年は、FigmaとLottieを連携させたWebアニメーションの作成方法をご紹介しました。

▼昨年度の記事はこちら

tech.excite.co.jp

Figmaのプロトタイプ機能とLottie用プラグインを活用すれば、CSSJavaScriptなどのコーディングや After Effects を使わなくても、比較的簡単にWebアニメーションを作成できます。

これはこれで、実装連携しやすくとても良い手法なのですが「生成AI」の技術進化により、今や動画やアニメーション制作にもAIが活用できる時代に……!

そこで今回は、AIを使って動画アニメーション制作にチャレンジしてみました。

今年の私「AIに全部まかせてアニメーション動画を作ってみよう!」

🎄完成した動画がこちら

昨年と同じく「クリスマス」をテーマに作成しました。

映像だけでなくBGMもAI生成なんです!ここまでできると、ちょっと感動しますよね……!

使ったツール紹介と制作の裏側

今回使用したAIツールはこの2つです。

Gemini

Googleが開発した「マルチモーダル」対応のAIモデル。テキストだけでなく画像、音声、動画など複数の情報形式を同時に理解・処理できるのが最大の特徴です。

今回私は、『動画構成(ストーリー)の検討』や『イラスト素材の生成』、『動画生成用プロンプトの相談』に使用しました。

‎Google Gemini

Gemini
Gemini

Adobe Firefly

Adobeが開発した、クリエイター向けの生成AIファミリー。画像や動画生成だけでなく、オブジェクトの追加・削除、テキスト効果、ベクター生成など、幅広い機能があります。

今回私は、『動画の生成』に使用しました。

Adobe Firefly

Adobe Firefly
Adobe Firefly

手順① :Geminiで動画の構成(ストーリー)を検討

まずは、Geminiに「動画の構成案を考えて〜!」と、かなりざっくりお願いしました。

その中でも 『何も飾り付けされていない家にサンタが訪れ、ツリーを飾り、プレゼントを置いて帰っていく』 というシンプルなストーリーを採用しました。

ちなみに、『このストーリーこれいいね!』と伝えるとすぐに動画を制作してくれました…!(すごい👀)

Geminiによる動画生成
Geminiによる動画生成

手順② Geminiで素材を作る

次に、Gemini(Nano Banana)を使って元となるイラスト素材を生成しました。🍌

何もない部屋の画像
何もない部屋の画像

サンタさんやトナカイが飾り付けしている画像
サンタさんやトナカイが飾り付けしている画像

満足げに帰っていく画像
満足げに帰っていく画像

ここで驚いたのがテイストの維持です。 「この雰囲気のままで次のシーンを描いて」と頼むと、ちゃんと絵柄をキープしてくれる…!

シーンごとにキャラや部屋が別物になる……なんてこともなく、かなり使いやすいと感じました!

手順③ Adobe Fireflyで動画を生成

素材が揃ったらいよいよ動画化です。

今回は、複数の動画生成モデル(Veo、RunwayGen、Sora etc…)をツールを切り替えずに試せる Adobe Firefly を使いました。

生成した画像を設定して、まずはシンプルに

サンタさんとトナカイが家を訪れて、ツリーを飾りつけたり、プレゼントを置いて帰っていく

というプロンプトで生成。

すると……サンタが2人になったり、窓枠と顔が被ってしまったり…なかなかうまくいかない…💦

手順④ プロンプトをGeminiへ相談

何度か試してもうまくいかなかったので、再びGeminiに相談しました。

「Fireflyでこういう動画を作りたいんだけど、どう指示すればいい?」と聞いてみると、英語プロンプトを含むおすすめの指示文を提案してくれました。

その通りに試してみたところ……最初に紹介した動画が無事完成! 🙌

まとめ | Adobe Firefly ここがすごい✨

実際に使ってみて、「これは便利…!」と感じたポイントをいくつか紹介します。

▶️ 生成した後に編集できる

「生成して終わり」ではなく、生成後に調整・編集できるのが便利だと思いました! * 気になるカットだけ作り直す * テキストやエフェクトを追加する * 続きを生成させる といったことが簡単にできるので、試行錯誤しやすくいいなと感じました。

生成後の編集画面
生成後の編集画面

🎵 音楽(BGM)まで一緒に生成してくれる

動画だけでなく、BGMも一緒に生成してくれるのが便利でした。

また気に入らなかったら「サウンドトラック」や「サウンドエフェクト」も新規で生成し、それを動画に当てこむこともできるので、雰囲気に合った音楽を一から探したり、別ツールで作ったりする必要がなく、「とりあえずそれっぽいBGM付きの動画を作りたい」という場面では、かなり助かります。

生成後の編集画面
生成後の編集画面

🤖 モデル数が多い

Adobe Fireflyでは、Firefly Videoの他にVeo、Runway Gen、Sora、Rayなどなど複数の動画生成モデルを同じツール上で試せるのが大きな魅力です。「このモデルだとどうなる?」「別のモデルならもう少し安定するかも?」といった比較がしやすく、実験しながら作れるのが楽しかったです。

モデル選択
モデル選択

AIで動画を作ってみての感想

もし今回の動画を素材の描き起こしやAfter Effectsでのアニメーション制まで、すべて手作業で行っていたら、数日はかかっていたと思います。

それが、実作業1時間程度で「ストーリーのある一本の動画」として完成したのは、正直かなり衝撃でした。

みなさんもぜひ、AIと一緒にクリエイティブを楽しんでみてください!最後まで読んでいただき、ありがとうございました 🎄✨

Claudeで認識合わせから始めた、診断コンテンツ開発

こんにちは!
Life & Wellness事業部でデザインを担当しているサカイです。

Qiitaアドベントカレンダー16日目を担当しています。

qiita.com

今回は、世界メンタルヘルスデーに向けて、診断コンテンツを作ることになりました。 その中で、AIを使いながら進め方を工夫した部分について書いていきます。

背景:時間が限られた中で診断コンテンツを作ることになった

担当サービスで診断コンテンツを作ることが決まりましたが、
スケジュールにはあまり余裕がありませんでした。

普段の業務はこのような流れで進めています。

普段の業務の進め方

しかし、この進め方だと自分がデザインFIXするまで実装に入りづらい状態となり、どうしても待ち時間が発生してしまいます。この順番で進めると実装やテストに十分な時間を取るのが難しそうでした。

全員が作業を止めずに進める方法

そこで、全員が作業を止めずにリリースする方法を考えました。

Claudeでワイヤーを作って認識を揃えたうえで、その後に作業を分担するという進め方をしました。

大枠のイメージをClaudeで作る

Claudeでモックを作成しました。普段の実装がHTMLベースであるため、モックの段階から実装に近い形で出力できる点が便利でした。 おおまかな仕様を入れて、イメージと違う部分を指摘しながら調整しました。

SNS導線をここに置いてほしい」と指示するとすぐに作り直してくれて、

企画と会話をすすめながら修正していきました。

claudeで動くモックを作成

作ったものをすぐにURLで共有して確認してもらえるところも、Claudeの便利なところでした!

ここで全員の共通認識ができたので、全員が作業するターンに入ります。

コードを一式エンジニアに渡して組み込んでもらい、
デザイナーの自分はClaudeで作ったものをベースに次の作業をします。

html.to.designでFigmaに取り込む

Claudeで作ったモックは細かい修正が難しいので、 html.to.designを使ってFigmaに取り込み、具体的なコンテンツ内容を検討していきました。 html.to.designはWebサイトをFigmaの編集可能なデザインに変換するプラグインで、作成したモックをFigmaで編集したいときに便利でした!

html.to.design

デザイン作成

デザインの実装

デザインの方向性がある程度固まったところで、エンジニアが実装ほぼ終了していたので、デザインを実装していきました。

その過程で、 企画が考えた設問をカーソルを使ってJSONにするなど、渡すデータについてもAIを活用しています。

作成した診断コンテンツはこちらです! ぜひやってみてください。

counselor.excite.co.jp

よかったこと

この進め方を取ったことで、

  1. 短期間で合意形成ができた
  2. 実装とデザインを並行して進められた
  3. 手戻りを最小限に抑えられた

というメリットがありました!

おわりに

時間がない中では、モックでも「こういうものを作る」というイメージがチーム内で早めに揃っていることが、その後の進めやすさにつながると感じました。

AIを使うことで、こうした認識合わせのためのモックをさっと用意できるようになったのはとても助かっています。

今後も、まずはイメージを揃えるための手段として、うまく活用していきたいと思います。

リビルドを始めた話

はじめに

こんにちは。新卒3年目の岡崎です。

アドベントカレンダー10日目の記事です。

qiita.com

BB事業部では、2025年12月現在、リビルドを進めています。その事例を今回は紹介していきたいと思っています。

なぜリビルドをするのか

BB事業部でリビルドを進める背景には、いくつかの課題があります。

まず、プロジェクト自体がかなり古くなっており、不要なコードが大量に残っている状態になっています。その結果、「どのコードが使われていて、どれが使われていないのか分からない」といった状況が発生しています。

また、使用しているライブラリの中にはEOL(サポート終了)を迎えているものもあり、バージョンアップができないケースもあります。これはセキュリティ面でのリスクにつながるだけでなく、アップデートによるパフォーマンス向上や新機能といった技術的な恩恵を受けられないという問題もあります。

さらに、BB事業部にはLaravelを使用したプロジェクトがある一方で、BEARというPHPフレームワークを使用しているプロジェクトもまだ残っています。BEARは現在では利用機会が少なく、新しく入ったメンバーほど馴染みがなくなっています。そのため、「今後あまり使うことのない技術を、このプロジェクトのためだけに集中的に学ぶ必要がある」という状況が生まれてしまっています。

このような不健全な状態は、結果として開発効率の低下や属人化を招く可能性が高いと考えています。

以上の理由から、BB事業部ではシステムのリビルドを進めていく流れとなりました。

どんな構成を目指すのか

BB事業部では現在、多くのリポジトリが存在しています。そのため、まずはこれらを1つのリポジトリに集約し、モノレポ構成を採用する方針としました。

モノレポとは

モノレポとは、複数のプロジェクトやサービスを1つのリポジトリで管理する開発手法です。

モノレポの例

repo/
├── frontend/
├── backend/
├── batch/

モノレポを採用することで、コードを一元管理でき、変更の影響範囲を把握しやすくなります。 一方で、リポジトリが肥大化しやすいといったデメリットもあります。

しかし、現状ではリポジトリが増え続けていること自体が課題となっているため、これ以上リポジトリを増やさないための対策として、今回はモノレポ構成を選択しました。

アーキテクチャ

今回の設計方針的には、主にリポジトリーパターンを採用しています。

リポジトリーパターンとは

リポジトリパターンでは、Controller → Service → Repositoryという責務分離の構成を取ります。

• Controller:リクエストの受け取り・レスポンスの返却

• Service:ビジネスロジックの実装

• Repository:データベースや外部サービスとのデータのやり取り

このように役割を明確に分けることで、各層の責務がはっきりした設計になります。

リポジトリパターンを採用した理由

この構成を採用した理由は以下の通りです。

• 層を意識した開発ができ、コードの見通しが良くなる

• クリーンアーキテクチャやDDDは、Web開発の現場ではオーバースペックになる場合があり、設計を保ったまま運用し続けるのが難しいことがある。そのため、できるだけシンプルで、チーム全体が理解しやすい構成を選択した

• Repositoryを切り出すことで依存関係が分離され、Unit Testを導入しやすくなる

まずはチーム全体ができるだけシンプルな形で、みんなで開発できることを目指して、この設計を採用しています。

インフラ

インフラの構成管理(IaC)には Terraform を採用しています。

Terraformは、クラウドに依存しにくいという特徴があり、コードベースでインフラを管理できる点や、初学者でも比較的取り組みやすい点を評価して採用しました。

一方で、既存リソースとの整合性を取る作業が想像以上に難しく、特に既存環境がある状態からの導入では、運用面で考慮すべき点が多いことも分かりました。

そのため、現在振り返ると、既存リソースが多い環境ではCloudFormationを選択する判断もあり得たと感じています。

現在、やってみてよかったこと

リビルドを進める中で、開発効率が向上していると実感しています。 実際に、これまで3日ほどかかっていた実装が、1日で完了するケースも出てきました。

また、インターン生にも同じ設計方針で実装を行ってもらいましたが、大きくつまずくことなく、比較的短期間で構成に慣れ、開発に取り掛かることができていました。

設計をある程度揃えたことで、新しく参加したメンバーでも理解しやすい状態になってきていると感じています。

最後に

今回、「今後も開発を続けていくために必要な改善を行いたい」と考え、リビルドを始めました。 しかし、現時点ではまだ道半ばです。

リビルドは短期間で終わるものではなく、継続的な取り組みが必要になります。 それでも、少しずつ改善を積み重ねていくことで、開発しやすい環境や、チーム全体の生産性向上につながっていくと考えています。

今後も地道な改善を続けながら、より良い形を目指していきたいと思います。

StreamlitでチャットUIと簡易ダッシュボードを作ってみる

こんにちは、エキサイトでエンジニアをしております、吉川です。 エキサイトHDアドベントカレンダー2025の14日目の記事になります。

qiita.com

Streamlitとは

Streamlitは、Pythonでデータサイエンスや機械学習のWebアプリケーションを素早く構築できるオープンソースフレームワークです。HTMLやCSSJavaScriptを書くことなく、Pythonのコードだけでインタラクティブなダッシュボードやデータ可視化ツールを作成できます。

特徴として以下が挙げられます。

  • シンプルな記法: st.write()st.button()など、直感的なAPIで簡単にUIコンポーネントを配置できる
  • 自動リロード: コードを変更すると即座にブラウザに反映される開発体験
  • 豊富なコンポーネント: グラフ、テーブル、チャットなど、データアプリに必要な機能が揃っている

今回は、Streamlitを使ってチャットUIとグラフUIを実装してみながら、その使い勝手と適用場面について考えてみます。

実際に使ってみる

事前準備(インストール)

以下でインストールします。

pip install "streamlit>=1.27" pandas numpy

チャットUIの実装

Streamlitではst.chat_messagest.chat_inputを使うことで、簡単にチャットUIを構築できます。

import streamlit as st

st.title("チャットアプリ")

# チャット履歴を保持
if "messages" not in st.session_state:
    st.session_state.messages = []

# 過去のメッセージを表示
for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.write(message["content"])

# ユーザー入力
if prompt := st.chat_input("メッセージを入力"):
    # ユーザーメッセージを追加
    st.session_state.messages.append({"role": "user", "content": prompt})
    with st.chat_message("user"):
        st.write(prompt)
    
    # アシスタントの返答(ここでは単純なエコー)
    response = f"あなたは「{prompt}」と言いました"
    st.session_state.messages.append({"role": "assistant", "content": response})
    with st.chat_message("assistant"):
        st.write(response)

このコードをapp.pyとして保存し、以下のコマンドで実行できます。

streamlit run app.py

たったこれだけで、ChatGPTのようなチャットインターフェースが完成します。セッション管理もst.session_stateで簡単に実装でき、LLMと連携すれば本格的なチャットボットもすぐに作れます。

グラフUIの実装

データ可視化も非常にシンプルです。Streamlitは主要なグラフライブラリをサポートしています。

import streamlit as st
import pandas as pd
import numpy as np

st.title("データ可視化ダッシュボード")

# サンプルデータ生成
np.random.seed(0)
chart_data = pd.DataFrame(
    np.random.randn(20, 3),
    columns=['A', 'B', 'C']
)

# 折れ線グラフ
st.line_chart(chart_data)

# インタラクティブな要素
selected_column = st.selectbox("表示する列を選択", ['A', 'B', 'C'])
st.area_chart(chart_data[[selected_column]])

Streamlitを立ち上げたまま(再起動してもOK)、app.pyファイルの中身をこのコードに変えると、複数のグラフとインタラクティブな選択UIを持ったダッシュボードが表示されます(ファイル変更時は基本的に自動で再読み込みされます)。

Streamlitの魅力

ここまで見てきたように、Streamlitの最大の魅力は圧倒的な開発速度です。数十行のPythonコードで、綺麗なUIが即座に立ち上がります。プロトタイプを素早く作成したい場合や、データサイエンティストがフロントエンドの知識なしでツールを作りたい場合に非常に有効です。

向いているケース、向いていないケース

Streamlitの制約

開発速度が速いStreamlitですが、万能ではありません。いくつかの制約があります。

1. 認証・認可の機能が弱い

Streamlit自体には本格的な認証機能がありません。Streamlit Cloudの認証機能やサードパーティライブラリを使う方法はありますが、細かい権限制御や複雑な認証フローには対応しづらいです。

2. デザインのカスタマイズ性が低い

用意されたコンポーネントの範囲内でしかUIを構築できず、独自のデザインシステムを適用したり、細かいレイアウト調整をするのは困難です。CSSでのカスタマイズも可能ですが、本格的に行うと結局手間がかかります。

3. コードが複雑化しやすい

Streamlitは上から順に実行されるため、状態管理やイベント処理が複雑になると可読性が低下します。st.session_stateでの状態管理は便利ですが、アプリが大きくなるとコードの見通しが悪くなりがちです。

4. パフォーマンスの限界

ユーザーの操作ごとにスクリプト全体が再実行される仕組みのため、大規模なデータ処理や複雑な計算を含む場合、レスポンスが遅くなることがあります。

向いているケース

以下のような場面ではStreamlitが非常に有効です:

  • 社内向けダッシュボード: デザインよりも機能性が重視され、認証も基本的なもので済む場合
  • データ分析のプロトタイプ: 仮説検証や実験的なツールを素早く作りたい場合
  • デモアプリケーション: 機械学習モデルやアルゴリズムの動作を視覚的に見せたい場合
  • 個人プロジェクト: 小規模で開発リソースが限られている場合

これらのケースでは、Streamlitの「速く作れる」という利点が欠点を大きく上回ります。

向いていないケース

一方、以下のような場面では別の技術選定を検討すべきです:

  • 外部ユーザー向けプロダクト: デザインやUXの品質が重要な場合
  • 複雑な権限管理が必要: 組織やロールに応じた細かいアクセス制御が必要な場合
  • 高度なインタラクション: 複雑なUI/UXやリアルタイム性が求められる場合
  • 長期運用が前提: コードベースが大きくなることが予想される場合

こうした要件がある場合は、最初からReactやVue.jsなどのフロントエンドフレームワークと、FastAPIやDjangoなどのバックエンドフレームワークを組み合わせた構成にする方が、長期的には開発効率が高くなるでしょう。

まとめ

Streamlitは、Pythonだけで素早くデータアプリケーションを構築できる強力なツールです。ただしUIを数十行のコードで実現できる代わりに、認証機能(特に細かな認可)を自前で用意しづらい、デザインの自由度が低い、状態管理が複雑になるとコードが見通しづらい、といった制約があることも事実です。個人的には最初は簡単に作れても、要件が増えるにつれて技術的な限界に直面しやすいと感じています。

重要なのは、「Streamlitでも十分なのか」を冷静に判断することです。社内ツールやプロトタイプなど、スピード重視で機能面にフォーカスできる場面では最適な選択肢となります。一方で、外部公開するプロダクトや長期運用が前提のシステムでは、初期の開発速度よりも拡張性や保守性を優先し、従来のフロントエンド・バックエンド分離構成を選ぶ方が賢明でしょう。

適材適所でStreamlitを活用し、開発効率を最大化していきましょう。

プライベート環境内のn8nでSlackイベントを受ける

こんにちは、エキサイトでエンジニアをしております。吉川です。 エキサイトHDアドベントカレンダー2025の7日目の記事になります。

qiita.com

この記事の前提とゴール

この記事では 「プライベート環境内にセルフホストしたn8n」 で、Slackのイベント(Events API)をトリガーにワークフローを起動するための構成を紹介します。

  • 前提
    • AWSVPC / EC2 / API Gateway / Lambda)の基本用語が分かる
    • Docker / docker compose が使える
    • Slackアプリを作成できる権限がある
  • ゴール
    • Slack →(インターネット)→ API Gateway → Lambda →(VPC内)→ n8n という経路で、Slackイベントを安全にn8nへ届ける

n8nとは

n8nは、ノーコード/ローコードで様々なサービス間の連携を実現できるワークフロー自動化ツールです。トリガーとアクションを組み合わせることで、複雑な業務プロセスを自動化できます。

n8nには大きく分けて2つの利用方法があります:

  • n8n Cloud: n8nが提供するクラウドサービス。インフラの管理が不要で、すぐに利用開始できます
  • セルフホスト: 自社のサーバーやクラウド環境に自分でn8nをデプロイする方法。カスタマイズ性が高く、データを自社環境内に保持できます

今回は、セキュリティ要件の観点からセルフホスト版のn8nをプライベートサブネット内に構築し、そこでSlackトリガーを利用する方法について解説します。

セルフホスト版のn8nをプライベートサブネット内に立てる

EC2インスタンスの準備

まず、AWSのプライベートサブネット内のEC2インスタンスを立ち上げ、インスタンス内で以下のようにcompose.yamlファイルを作成します。

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    ports:
      - "5678:5678"
    environment:
      - GENERIC_TIMEZONE=Asia/Tokyo
      # Slackに登録するRequest URL(=外部公開URL)のベース。
      - WEBHOOK_URL=${PUBLIC_WEBHOOK_BASE_URL}
    volumes:
      - n8n_data:/home/node/.n8n
volumes:
  n8n_data:

compose.yamlを作成したら、以下のコマンドでn8nを起動します。

# DockerとDockerComposeはインストールされている前提
# n8nコンテナの起動
docker compose up -d

PUBLIC_WEBHOOK_BASE_URLcompose.yaml と同じ階層の .env などで設定します(Slackに登録するRequest URLのベースなので https のURLになります)。

セキュリティグループの設定

プライベートサブネット内のn8nは、外部からの不正アクセスを防ぐために、セキュリティグループで厳格なアクセス制御を設定します。

  • インバウンドルール:
    • ポート5678(n8nのUIアクセス):社内の踏み台/VPN/SSM経由など、運用方針に沿った経路のみに限定
    • ポート5678(Lambda → n8n 転送用):後述のLambda(またはLambdaに紐づくセキュリティグループ)からのみ許可

この設定により、社内からのみn8nの管理画面にアクセスでき、外部からの直接アクセスは遮断されます。

セルフホスト版n8nとSlackトリガー

Slackトリガーの基本設定

n8nでSlackトリガーノードを追加すると、SlackのEvent Subscriptionsに登録するためのRequest URL(Webhookエンドポイント)が提示されます。

このURLをSlackアプリのEvent Subscriptionsに設定することで、Slackでのイベント(メッセージ投稿、リアクション追加など)をトリガーにワークフローを実行できます。

問題:SlackのIPアドレスが固定されていない

ここで問題が発生します。Slackはグローバルな分散インフラストラクチャで運用されており、Webhookリクエストの送信元IPアドレスが固定されていません。そのため、セキュリティグループで特定のIPアドレスのみを許可する設定では、Slackからのリクエストを受け付けることができません。

かといって、すべてのIPアドレスからのアクセスを許可してしまうと、セキュリティリスクが高まり、プライベート環境に配置した意味がなくなってしまいます。

Lambdaを経由してn8nに送る

この問題を解決するために、AWS API Gateway + Lambdaを中継ポイントとして利用します。

この構成のポイントは以下です。

  • Slackは インターネット上のHTTPSエンドポイント(= API Gateway)にしか投げられない
  • n8nは プライベート環境内に閉じたまま、Lambdaからのみ到達可能にする
  • Slackリクエストは IP制限ではなく署名検証(Signing Secret) で正当性を担保する

注意点として、SlackのEvents APIには「最初のURL検証(url_verification)」や「応答は概ね3秒以内」などの要件があるため、Lambda側でそれを満たす実装にします。

API Gatewayの設定

API GatewayREST APIを作成し、エンドポイントを公開します。このURLをSlackアプリのEvent SubscriptionsのRequest URLに設定します。

Lambda関数の実装

Lambda関数では以下の処理を実装します。

プライベートサブネット内にリクエストを送信するため、LambdaのVPC設定で上記のEC2と同じVPC・サブネットを設定します。またEC2のセキュリティグループで、Lambdaのセキュリティグループからのアクセスを許可します。

また環境変数(必要ならSecrets Manager等)にSLACK_SIGNING_SECRETN8N_TRIGGER_URL を設定します。N8N_TRIGGER_URL はn8nが表示するWebhook URL(上記のPUBLIC_WEBHOOK_BASE_URL)の パスはそのままに、ベースだけを http://<EC2のIP>:5678 にしたものを使います。

Lambdaのコードは以下のようになります。

import os
import json
import hmac
import hashlib
import base64
from datetime import datetime
import requests

# Slackからのリクエスト検証 
def validate_request_from_slack(slack_signing_secret: str, headers: dict, body: str) -> bool:
    timestamp = headers.get("X-Slack-Request-Timestamp")
    slack_signature = headers.get("X-Slack-Signature")

    # 直近のリクエストか検証
    current_time = int(datetime.now().timestamp())
    if abs(current_time - int(timestamp)) > 60 * 5:
        return False

    # 署名検証
    sig_basestring = f"v0:{timestamp}:{body}"
    signature = (
        "v0="
        + hmac.new(
            slack_signing_secret.encode("utf-8"),
            sig_basestring.encode("utf-8"),
            hashlib.sha256,
        ).hexdigest()
    )
    return hmac.compare_digest(signature, slack_signature)

# n8nへのリクエスト転送
def send_n8n(n8n_trigger_url: str, body: dict) -> None:
    requests.post(
        url=n8n_trigger_url,
        headers={"Content-Type": "application/json"},
        json=body,
    )

def lambda_handler(event, context):
    headers = event.get("headers") or {}
    body = event.get("body") or ""
    if event.get("isBase64Encoded"):
        body = base64.b64decode(body).decode("utf-8")

    slack_signing_secret = os.environ.get("SLACK_SIGNING_SECRET", "")
    if not slack_signing_secret or not validate_request_from_slack(slack_signing_secret, headers, body):
        return {"statusCode": 401, "body": "invalid signature"}

    # SlackのURL検証(Event Subscriptionsを有効化する際に必須)
    try:
        payload = json.loads(body) if body else {}
    except json.JSONDecodeError:
        payload = {}
    if payload.get("type") == "url_verification":
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"challenge": payload.get("challenge", "")}),
        }

    n8n_trigger_url = os.environ.get("N8N_TRIGGER_URL", "")
    if not n8n_trigger_url:
        return {"statusCode": 500, "body": "missing N8N_TRIGGER_URL"}

    send_n8n(n8n_slack_trigger_url, payload)

    return {"statusCode": 200, "body": "ok"}

ポイント:

  • SlackのEvent Subscriptionsは最初に url_verification を投げてくるため、challenge応答がないと有効化できない
  • 署名検証は 「受け取った生のbody」 に対して行う(JSONとしてパースして並び替えると署名が一致しなくなる)

まとめ

セルフホスト版のn8nは、それ自体は無料(EC2料金は別途かかる)で使用でき、データも自社環境内に保持できるため、機密情報を扱う業務フローでも安心して利用できます。

また、非エンジニアの方でもn8nのGUIを使って安全に業務自動化を進められるようになり、組織全体の業務効率化に貢献できると考えています。

セキュリティ要件が厳しい環境でのワークフロー自動化を検討されている方の参考になれば幸いです。

テックブログのカテゴリ構成を見直した話

こんにちは!SaaS・DX事業部デザイナーの鍜治本です。 Qiitaアドベントカレンダー15日目を担当しています🎄

qiita.com

今回は、社内で運用しているテックブログの「カテゴリ構成」を見直した話を書きます。 記事の内容や技術そのものではなく、テックブログをどう整理・運用していくかという、少し裏側の話です。

なぜカテゴリ構成を見直すことにしたのか

このテックブログは、自分が入社する前から運用されていました。
当時は明確な運用ルールはなく、「まずは書くことを優先する」スタンスだったと聞いています。

立ち上げフェーズとしては自然な判断で、記事が積み重なったからこそ、カテゴリ構成の課題が見えるようになってきました。

ブログ基盤としての「はてなブログ

ブログ基盤には、はてなブログを利用しています。

  • 1つの記事に複数カテゴリを付けられる
  • カテゴリに階層構造はない

自由度が高い一方で、ルールや設計をしないと、情報構造が散らかりやすい特性があります。

自分の過去ブログも自由にカテゴリを設定してました

改善前に抱えていたカテゴリの課題

粒度が揃っていないカテゴリ

改善前は、カテゴリの粒度がかなりバラバラでした。

登録されていたカテゴリーの一覧
例えば、

  • 「技術」という大きなカテゴリ
  • その中に並ぶ、言語名・ライブラリ名・概念的な話題

といった形で、抽象度の異なるものが同列に存在していました。

カテゴリ一覧を見ても、

  • このブログは何を扱っているのか
  • どんな切り口の記事が多いのか

が直感的に分かりづらい状態だったと思います。

運用ルールが存在しなかった影響

また、カテゴリに関する運用ルールがなかったため、

  • どのカテゴリを付けるかの判断が書き手ごとに異なる
  • 記事が増えるほど整理が難しくなる

といった問題も目立つようになってきました。

抽象的なものから具体的なものまで入り混じっている状態

カテゴリ構成をどう見直したか

今回のカテゴリ整備は、自分の判断で進めているものです。
現時点では正式な運用ルールではなく、まずは構造を整理してみる、という位置づけになります。

今後、ブログの状況を見ながら、ガイドラインとして整理していくことを想定しています。

親子構造を“間接的に”持たせる

はてなブログには階層カテゴリがないため、その制約の中で構造が伝わるような設計を考えました。

例えば、以下のような形です。

技術組織
└ 社内技術カンファレンス
 └ 年ごとのアーカイブ

カテゴリ名の付け方によって、間接的に親子関係が分かるようにしています。

見せ方の部分で階層構造(風)に

これにより、

  • 取り組み単位で記事をまとめられる
  • カテゴリ一覧から全体像が把握しやすくなる

といった効果を狙いました。

カテゴリ構造はこちらのサイトを参考に、ChatGPTと相談しながら進めて行きました。

maysun53.com

参考にした技術ブログ

カテゴリ設計を考えるにあたり、いくつか他社の技術ブログも参考にしました。

  • カテゴリの切り方
  • 年次・イベント単位での整理
  • 一覧性の作り方

「どんな情報を、どんな単位で見せたいか」が明確なブログほど、カテゴリ設計も整理されている印象でした。

参考にさせていただいたテックブログ(同じはてな形式のものを中心に調べました)
tech-blog.cluster.mu

www.m3tech.blog

techblog.tebiki.co.jp

developers.freee.co.jp

実際にやってみて分かったこと

良かった点

実際に整理してみて、良かったと感じている点です。

  • カテゴリ一覧がかなりスッキリした
  • 技術組織としての取り組みが見えやすくなった
  • 社内イベントや継続的な活動をまとめて追えるようになった

「記事単体」ではなく、「活動のまとまり」として読める構造になったのは大きな変化でした。

Before:アルファベット順に並ぶだけ After:抽象>具体の構造

デメリットと悩み

一方で、デメリットや難しさもあります。

  • 親カテゴリ自体にも、ある程度の記事や説明が必要になる
  • 気軽にカテゴリを増やせなくなった
  • まだ綺麗にまとまりきっていない部分もある

構造化した分、「とりあえずカテゴリを作る」ができなくなり、設計コストが上がってしまう結果に。

他社技術ブログを見て感じたこと

他社の技術ブログを見ていると、

  • カテゴリ数を意図的に増やさない
  • カテゴリ自体をあえて非表示にしている

といった設計も多く見かけました。

「カテゴリは必ずしも前面に出す必要はない」、という選択肢に気づけたのも、今回の整理の収穫です。

今後について

このブログは、検索経由で辿り着く方や、就職・転職の観点で見てくださっている方も多いと考えています。

だからこそ、

  • 構造が分かりやすいこと
  • 目的の記事に辿り着きやすいこと

を意識しながら、カテゴリ構成も運用しつつ育てていくつもりです。

ルール化できる部分は、少しずつ整えていければと思っています🙏

AI × Webデザインで必ずチェックしている有識者たち【私的まとめ】

こんにちは!エキサイトお悩み相談室でデザインを担当しているサヅカです。

AI×Webデザインまわりの情報は日々アップデートされていて、 追いきれないな…と感じることも多くなってきました。

今回はその中でも、個人的に参考にしている有識者の方々をまとめてみました。情報収集源は主にXになります。

👇こちらはExcite Holdings Advent Calendar 2025の12日目の記事です。

qiita.com

生成AIの実験・最新情報

ミヤマさん@mmmiyama_D

投稿が毎回「え、そんな発想あるの…?」と驚かされるタイプのAI情報通。 生成AIの使いこなし、検証、ちょっと変態的な探索まで幅広く、常に情報が早い。

→プロンプト力を上げたい時・AIの限界値を知りたい時に見る人。


すぐるさん@SuguruKun_ai

ChatGPT(チャッピー)界隈の有識者。分かりやすさが段違い。 AI解説の図解がめちゃくちゃ丁寧で、「これを最初に知りたかった…」と思う内容が多い。 更新頻度も高く、初心者〜中級者の学びにちょうどいい。

→ChatGPT 最新情報のキャッチアップはこの人で十分。


KAWAIさん@kawai_design

とにかく網羅性が高い。AIツール紹介が“実務目線”でありがたい人。 単なる新ツール紹介ではなく、 「デザイナーはどう使えるのか?」 「どこが強みか?」 まで噛み砕いてくれる。 自身のブログもすごく丁寧で、体系立った学びが得られます。

→ 色んなAIツールを効率よくキャッチアップしたい時の定番。

思考法・メタ視点(デザインの未来)

DeNA 久田歩さん@ayumu_hisada

AI × デザインの思考法をアップデートしてくれる存在。 DeNAのデザイン組織を率いており、AI活用の文章は本当に毎回深い。 特にCocoda 寄稿記事は “AI でデザインがどう変わるか” を俯瞰して語っていて、見逃せません。

→ 「デザイナーの役割ってどう変わる?」と考えたい時に必ず読む人です。

https://cocoda.design/ayumuhisada/p/p59bae5f4dc03 cocoda.design


Brandonさん@BrandonKHill

アメリカのWebデザイン・AIトレンドを掴める貴重な発信者。 btraxのブログでは、海外のUI/UX、AIプロダクト、制作現場のリアルが分かる記事を多数執筆。 視点がグローバルで、日本でまだ出回っていない考え方が拾えると思います。

→ AI × Web制作を世界目線で理解したい時に最適。

https://blog.btrax.com/jp/category/design/ blog.btrax.com

他にも紹介したい方はたくさんいるのですが、 今回はその中でも特にチェックしている5名をピックアップしてみました。本当に有り難い神情報ばかり発信していて有り難いです…🙏

ちなみに弊社では、Slack上でAIに関する情報交換チャンネルをいくつか運用していて、 デザイナーやエンジニアだけでなく、 企画の方々からも「こんな情報があったよ!」と自然にシェアが生まれています。 職種を超えてAIの話題で盛り上がれるのは、ポジティブな変化だと思っています。

また最近は、デザイナーの中でも 「AIをどう使うか」だけでなく「どう自動化していくか」への関心も高まってきました。 その一環として、弊部署ではn8nをみんなで使えるようになろう、という取り組みを進めています( ˘ω˘ )🔥

n8nでどんなことをしているのかは、また別の記事で紹介できればと思います!

ウーマンエキサイトで連載中!AIコミックの制作フローを公開します

こんにちは、エキサイト株式会社のデザイナーの山﨑です。

Excite Holdings Advent Calendar 2025 の8日目を担当させていただきます。

今回は、現在エキサイトが運営するメディア「ウーマンエキサイト」でチャレンジしている、AIコミックのイラスト制作方法についてご紹介します。

はじめに:AIコミックとは?

「AIコミック」とは、脚本や作画のプロセスにおいて生成系AIを活用して制作された漫画のことです。

今回は、実際にウーマンエキサイトで連載していた『家族より整った部屋が大事?』という作品を例に、その制作の裏側をご紹介します。

通常、漫画制作には多くの工程がありますが、今回は「脚本」が決まった後の「ネーム・生成・調整」の部分に焦点を当てて解説していきます。

1. ネーム制作

まずは「ネーム」の作成です。 一般的な漫画のネームとは異なり、この段階では絵を描き込むことはせず、セリフとト書き(付箋)のみで構成していきます。

この状態で編集部に提出し、構成のチェックをお願いします。ここでOKが出たら、AIによる作画フェーズに入ります。

構成のポイント

読者を飽きさせず、かつAIでの生成をスムーズにするために、以下の点を意識しています。

  • 「ヒキ」を作る
    • 記事のサムネイル画像としても使えるような、インパクトのある「ヒキ(興味を惹く)」になるコマを作ります。

  • カメラアングルの使い分け
    • AI生成だと単調なバストアップ(胸から上の構図)ばかりになりがちです。
    • 読者が飽きてしまわないよう、意識的にロングショット・ミドルショット・アップショットを使い分ける指示を入れます。

他にも、吹き出し吹き出しの間にキャラクターの顔を挟むことで、読者がスムーズにセリフとキャラの顔の表情が目に入るようになど構成に工夫しています。

2. 画像生成

ここが最も時間がかかる、制作のメインパートです。

AIで漫画を作る際、最大の課題となるのが「作画揺れ(キャラクターや絵柄の不統一)」です。これを防ぐために、プロンプト(指示出し)には工夫が必要です。

プロンプトの固定化

毎回、以下のプロンプトをベースとして入力することで、絵柄の統一を図っています。

セリフ・吹き出しなし 線は細め/少女漫画風/ノイズなし/白黒20%/60%グレー含む

表情のコントロール

プロンプトだけでは顔の造形や表情が毎回変わってしまうことがあるため、生成時は毎回「参考にしたい表情」の画像を添付し、それをベースに生成させることでキャラクターの一貫性を保っています。

3. 調整 〜 完成

生成された画像をつなぎ合わせ、漫画の形式に組み上げます。 一度完成したものを編集部に提出し、フィードバックをもらいます。

  • 「この表情、もう少し悲しげに」
  • 「ここの構図をわかりやすく」

といったコメントを元に、再生成やCLIP STUDIO PAINT等での修正(レタッチ)を行い、ブラッシュアップしていきます。

修正が完了すれば、無事完成です!

完成した漫画はこちらで読むことができます↓

woman.excite.co.jp

おわりに

今回は、ウーマンエキサイトで取り組んでいるAIコミックの制作フローをご紹介しました。

ちなみに制作時間は、1日1~2話くらいできるので大体4〜5時間くらいになります。早い時は1話あたり3時間で終わることもあります。

生成系AIを使うことで、絵を描く時間を短縮できる一方で、「いかに意図通りの絵を出力するか」というディレクション能力や、構成力が重要になると感じています。

これからも新しい技術を取り入れながら、読者の皆さんに楽しんでいただけるコンテンツを作っていきたいと思います。

GitHub PackagesのMaven Repositoryを使ってみる

こんにちは、エキサイト株式会社の平石です。

アドベントカレンダーの3日目を担当します。

qiita.com

今回は、GitHub Packagesの利用方法と、実際に運用としていく上で私が感じた課題をご紹介します。

はじめに

GitHub Packages は、コンテナやその他の依存関係を含むパッケージをホストおよび管理するためのプラットフォームです。
通常、こういったものを管理しようとすると自前でサーバーを立てて運用する必要があります。
しかし、GitHub Packagesを使うことで自前でサーバーを管理する必要がなく、なおかつソースコードの管理とパッケージの提供をGitHubという一つのサービス内で完結させることができます。

環境

本記事のソースコードは以下の環境で動作確認を行っています。 GitHub PackagesのMaven Repositoryを利用します。

  • Java 21
  • SpringBoot 3.4.0
  • Gradle 8.11

事前準備

GitHub Packagesを利用するためには、Personal Access Tokenが必要です。

Generate new token > Generate new token(classic)をクリックし、Select scopesのところでwrite:packagesと必要ならdelete:package の権限を選択してPersonal Access Tokenを作成します。
作成したトークンは忘れないように保存しておいてください。

このトークンを、Gradleから利用できるようにします。

~/gradle/gradle.propertiesまたはプロジェクトルート直下にgradle.propertiesファイルを作成し以下の内容を記述します。

gpr.user=<GitHubのユーザー名またはOrganization名>
gpr.key=<先ほど作成したトークン>

~/gradle/gradle.propertiesに記述すると全てのGradleプロジェクトでそのプロパティを利用できます。

プロジェクトルート直下にgradle.propertiesファイルを作成する場合には、誤ってコミットしないように注意しましょう。

こちらで記述したプロパティはbuild.gradleファイルで以下のように参照することができます。

project.findProperty("gpr.key")

また、GitHub Packagesで管理するパッケージはリポジトリと紐づく形になるので、GitHubリポジトリが必要です。
通常は、アップロード対象のパッケージのソースコードを管理しているリポジトリで良いと思います。

Gradleの設定

パッケージとして公開するプロジェクト(サブプロジェクト)のbuild.gradleに以下のように記述します。
今回はパッケージの公開にmaven-publishというプラグインを利用します。

{root}/test_project/build.gradle

repositories {
    mavenCentral()
}

sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21

group = 'com.example'
version = '1.0.0'

apply plugin: "maven-publish"

publishing {
    repositories {
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com/{ユーザー名またはOrganization名}/{repository名}")
            credentials {
                username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
                password = project.findProperty("gpr.key") ?: System.getenv("ACCESS_TOKEN")
            }
        }
    }
    publications {
        gpr(MavenPublication) {
            artifactId = 'test_project'
            from(components.java)
        }
    }
}

maven-publishプラグインの設定はpublishingの部分に記述します。
アップロード先のMaven Repositoryのurlhttps://maven.pkg.github.com/{ユーザー名またはOrganization名}/{repository名}となります。

また、アップロードには認証が必要なため、credentialsで認証情報を設定しています。
passwordには先ほどプロパティファイルに記述したPersonal Access Tokenを読み込むように設定しています。

GitHub Actionsから利用する際にはgradle.propertiesファイルに記述するより、環境変数に設定する方が扱いやすいです。
そのため、プロパティが見つからない場合にはSystem.getenv("環境変数名")環境変数から値を取得するようにしています。

Graldeプロジェクトを再ロードすると、project1:publishGprPublicationToGitHubPackageRepositoryというGradleタスクでGitHub Packagesにパッケージをアップロードできるようになっています。

./gradlew project1:publishGprPublicationToGitHubPackageRepository

このGradleタスクを実行すると、リポジトリのホーム(https://github.com/{ユーザー名またはOrganization名}/{リポジトリ名})のサイドバーのPackagesという欄にアップロードしたパッケージが表示されています。
そこをクリックすると、以下のようなページでパッケージの詳細を確認できます。

アップロードしたパッケージを利用するには、利用するプロジェクト(サブプロジェクト)のbuild.gradleで以下のように記述します。

project(':project2:controller') {

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-web'

        // 先ほどアップロードしたパッケージ
        implementation 'com.example:test_project:1.0.0'
    }
}

ライブラリは一つのサブプロジェクトだけでなく、プロジェクト全体で利用することも多いと思いますので、プロジェクトルートのbuild.gradleでパッケージを取得する先のMaven Repositoryを以下のように宣言しておくと良いでしょう。

allprojects {
    repositories {
        mavenCentral()
        maven {
            url = uri("https://maven.pkg.github.com/{ユーザー名またはOrganization名}/{repository名}")
            credentials {
                username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
                password = project.findProperty("gpr.key") ?: System.getenv("ACCESS_TOKEN")
            }
        }
    }
}

urlや認証情報の設定はアップロードの時とほぼ同じです。

GitHub Actionsからの利用

GitHub Packagesは、当然ながらGitHub Actionsからも利用できます。
GitHub Actionsを実行しているのと同じリポジトリを対象にパッケージをアップロードまたはダウンロードする場合には、認証時にPersonal Access Token以外にもGITHUB_TOKENを利用できます。

GITHUB_TOKENはActionsのワークフロー内で利用できる期限付きの特別なトークンで、${{ secrets.GITHUB_TOKEN }}と記述することで参照できます。

例えば、パッケージをアップロードするワークフローは、以下のように実現できます。

name: Publish
run-name: publish

on:
  workflow_dispatch

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Publish
        env:
          ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          ./gradlew project1:publishGprPublicationToGitHubPackageRepository

GITHUB_TOKENの代わりにPersonal Access Tokenを利用する場合には、リポジトリのSecretsにトークンを登録して利用することになるでしょう。

利用してみての感想

弊社では、複数のサービスで利用する「社内の共通基盤」のライブラリを各サービスを管理する個々のリポジトリから利用するために、GitHub Packagesの利用を検討していました。

調査をする中でメリットに感じた点と懸念点を以下に共有します。

メリット

GitHubだけで完結できる

ソースコードのバージョン管理にGitHubを利用しているのであれば、ライブラリの管理もGitHubで完結できるのは便利です。
多くのサービスを利用すればするほど、各サービスの管理をする必要がありますし、有料のサービスであればコストもかさみます。

利用が簡単

自前でサーバーを立てることなく、GitHubへの認証だけでライブラリのアップロード、ダウンロードができる点は導入のハードルが低いといえるでしょう。

懸念点

コスト

懸念点の一つにコストの問題があります。
パブリックなライブラリの管理は完全に無料で利用できますが、プライベートなライブラリの管理をしようとするとそうはいきません。

GitHub Packagesではプランごとに無料利用枠が決められており、それを超えると従量課金されていきます。

docs.github.com

課金はストレージと月当たりのデータ転送量の2つに応じて行われます。
ストレージに関しては、Maven RepositoryでのJavaのライブラリでの利用であれば、ほとんどの場合は無料利用枠を超えることはないと思いますが、問題はデータ転送量の方でしょう。

GitHub Actionsを利用する場合はデータ転送は無料と書かれていますが、GitHub Actionsを利用しているとみなされるのはGITHUB_TOKENというトークンを利用した場合だけのようです。
このトークンではリポジトリを跨いだパッケージへのアクセスができません。
そのため、Personal Access Tokenを使うことになりますが、こちらを用いた認証だとGitHub Actionsを利用しているとみなされないようです。 つまり、あるサービスのソースコードを管理しているGitHubリポジトリで実行されるワークフローから、別のリポジトリのPackagesで管理しているライブラリをダウンロードしようとすると課金対象になると考えられます。

したがって、ローカルからのパッケージのダウンロードとGitHub Actionsを使ってデプロイなどを行う際のパッケージのダウンロードが課金対象となるため、頻繁にデプロイ・リリースを行うような場合には無料利用枠を超える可能性は十分にあると思います。

認証方法

もう一つの懸念点が認証方法です。
実はこちらの方が、課題と感じている点です。(コストに関しては、どのようなサービスを利用しても有料なことが多いですし、ある意味仕方ないといえます。)

GitHub Packagesは現在のところGitHub Actionsで利用できるGITHUB_TOKENという一時的なアクセストークンか、個人ごとに作成するPersonal Access Tokenを用いた認証方法しかサポートしていません。

前述の通り、GITHUB_TOKENを用いた認証では別のリポジトリへのアクセスができないようなので、「社内の共通基盤」のようなパッケージを社内の多くのサービスから利用しようとするとPersonal Access Tokenを用いた認証方法しか利用できません。

しかし、このトークンはPersonalとあるようにあくまで「個人」に紐づいたトークンです。
ローカルへのダウンロードならこれでも良いですが、GitHub Actionsを通して利用する場合に個人に紐づいたトークンを積極的に利用したくないことも多いでしょう。
その人が異動や退職でいなくなった場合にアクセストークンが管理できなくなったり、無効になったりするかもしれないですし、Organizatinsの場合何らかの理由で一般のメンバーにはGitHub Packagesへのアクセス権を渡していない場合もあるでしょう。

このようなことから、リポジトリを跨ぐ場合でも使えるPersonal Access Token以外の何かしらのアクセス方法が欲しいと、個人的には考えています。

おわりに

今回は、GitHub Packagesの利用方法と私が感じた課題をご紹介しました。

GitHubという多くの個人や組織が利用しているサービスの上で簡単に利用できて便利ではあるのですが、プライベートなパッケージを管理する上ではコストや認証方法にやや課題が残りそうです。

では、また次回。

参考文献

今年制作現場で活躍した生成AIツール5選

こんにちは!エキサイトお悩み相談室でデザインを担当しているサヅカです。

今年は本当に「AIなしでデザインできないな…」と思うくらい、仕事のあらゆる場面で生成AIに助けられました。

この記事では、その中でも “実際の制作で何度も使った” 生成AIツールを5つ紹介します。 AI流行ってるけど結局どれが使えるの?と思ってる人の参考になれば嬉しいです!

🎄アドベントカレンダーやってます🎄 qiita.com

🏅5位:Layer Mate|日本人好みのUIをいい感じにしてくれる

UIを一気に“それっぽく”仕上げたいときにめちゃくちゃ便利だったのがfigmaプラグイン「Layer Mate」。色々試していますが、私は今のところLayer Mateが一番使いやすいなと感じています。

▼ よかったところ

  • ちょっとしたUIが洗練された雰囲気で生成される
  • 日本人が開発しているからか“日本人が好きそうなUI” に寄せてくれる感じがする
  • ラフ〜デザイン作成が圧倒的に時短

💬 今後に期待ポイント

  • 英語プロンプトが必要なので、毎回ChatGPTに訳してもらってから使ってました。

🏅4位:Figmaの画像生成|“仮の画像”をその場でサクッと

Figmaで仮画像を置きたいとき、これが地味に最強です。

  • いちいちAdobe Stockを開いて探さなくてもいい
  • ラフ段階のスピードが段違い
  • 「とりあえずの1枚」をその場で作れるのが便利

商用利用の観点は気にしつつも、プロトタイピングの速度が一気に上がったツールです🚀

🥉3位:Gemini|日本語の生成が急成長!

今年後半、一気に存在感を出してきたのがGemini。 特に Gemini 3.0(Nano Banana Pro🍌)では日本語も読めるレベルで画像生成されるようになり、より実務での利用頻度が上がりました。

ChatGPTと併用しており、

  • ChatGPT → 論理・UI改善・文章系
  • Gemini → 画像生成・ビジュアルアイデア出し

のような役割分担で使うのが個人的ベストでした。Gemini 3.0が出る前はChatGPT一択でしたが相棒交代も近い…?

🥈2位:Figma MCP × Cursor|コーディング工数が激減

Figma MCP × Cursorの組み合わせがどんどん精度上がっており、最初は微妙だな〜と思っていましたが、今では普通に実務で使っています。

▼ 特によかったところ

  • LP制作のコーディング工数が爆減した
  • JavaScriptが必要なコンポーネントハンバーガーメニューなど)もスキルが無くても動くレベルのコードを出してくれる
  • ちょっとした修正ならコード読まずにAIに「ここ直して」で済む

💬 今後に期待ポイント

  • セクションごとにコーディングし直したほうが早い場面もまだある
  • たまにレイアウトが崩れがち

とはいえ、この速度感で進化していくなら来年もっとヤバいことになるな…と期待大です☝️( ˘ω˘ )

🥇1位:ChatGPT|UI改善も画像生成もこなす相棒

なんだかんだで今年の相棒No.1はこれ☝️( ˘ω˘ )

ほぼ毎日使っていて、もはやデザインの一部と言っていいレベルです。

▼ どんなふうに使ってる?

  • Adobe Stockでいい画像が見つからないときの画像生成
  • 作ったデザインに対して改善ポイントを教えてもらう → 自分では気づけなかった改善点が出てくるので本当に助かる

  • UI改修案を企画に出す前の壁打ち

  • UIのCTRなど、スクショから数字の傾向をざっくり分析してもらう

雑談も、仕様質問も、企画の壁打ちも全部できる万能選手。 「とりあえずChatGPTに聞く」流れがもう習慣になりました。

まとめ

AIのおかげで「デザインの進め方」が変わった一年だったと思います。 ただ作業を早くするだけではなくデザインの質や考え方そのものにも影響を与えてくれるAIが増えたと感じました。

  • 仮説出し → AI
  • ラフ作り → AI
  • コーディング補助 → AI
  • データ解析補助 → AI
  • 最後の判断 → 自分

みたいな流れが自然にできあがり、「人がやるべきこと」に時間をしっかり使えるようになりました。

来年はもっとAIがデザインの現場に入り込んでくると思うので、引き続きいろいろ試していきたいと思います!

Affinity Designerを触ってみた

こんにちは!SaaS・DX事業部デザイナーの鍜治本です。
Qiitaのアドベントカレンダーが始まったので、1日目を担当しています🎄 社内メンバーで分担しながら書いていくので、ぜひ続きも読んでもらえると嬉しいです!

qiita.com

1本目は最近試してみた制作ツールの体感レビュー。
テーマは Affinity Designer で、Illustratorを長く使ってきた立場から「パス(カーブ)編集って実際どうなの?」を中心に書きます。
AI機能の比較というより、ローカル制作ソフトとしての話寄りです✍️

触った背景

普段の作業だとIllustratorのペンツールで、

みたいなものを作ることが多いです。
ツールに求めるものもシンプルで、「起動して」「いつもの流れで作れて」「パス編集がストレスなくできる」が個人的に外せない要素です。

学生時代に、全プリキュアを作ったりしました

最近のIllustratorは、AI機能がどんどん増えていて便利になっていますね。
自分にとっては、AI機能より前に“普通に起動して、いつものテンポで作れるか”がまず土台だと思っています。

少し前にIllustratorでオンライン絡みの挙動が崩れて、起動や動作が安定しなくなるバグがありました。しかも「オフラインで起動すると直る」みたいな状態で、制作ソフトとしては割と困る…😇

Xでも話題になっていたので、該当しそうなポストを置いておきます。
自分の環境だけじゃなさそう、という背景の補強として貼っています👇

調べたところ、Creative Cloud系はライセンス認証の都合でオンライン前提の設計になっているようで、ネットワークや認証まわりの不具合がアプリの起動体験に影響していたようです。

こういう話が出るたびに、制作ツールの“土台の強さ”を改めて見直したくなります。そこで前から気になっていたAffinity Designerを試してみた、という流れです。

第一印象

レイアウトも相まってPhotoshopみがあります
触り始めの第一印象は、ちょっとPhotoshopっぽい雰囲気を感じました。
UIのトーンもそうですし、レイヤーを中心にエフェクトを積んでいく構造が前面に出ていて、UIも含めてPSのワークフローに近い入口がある、という印象でした。

Affinityはレイヤーにエフェクト イラレはオブジェクトにアピアランスをかける
Affinityでは Layer Effects(FX) として影やぼかしなどをレイヤー単位で重ねられるようで、触っていて「レイヤースタイルを積む」空気感があります。
Illustratorにも近いことができるアピアランス機能がありますが、Affinityのほうは“レイヤー前提で触る流れ”として自然に入ってくる感じで、個人的には印象が良かったです✨

基本操作

操作面はショートカットも含めてだいぶ馴染みがあります。
完全に別ツールをゼロから覚える、というより「だいたいこのへん触ればいつもの感じでいけそう」で早めに掴めそうです。

よく使いそうな機能のショートカットキー比較

パス編集が良かった

今回Affinityを使った作業はライトめです。

  1. 画像→パス化(ベクタートレース)
  2. 追加のテキスト→アウトライン化
  3. そのあとカーブ調整をしてみる

という流れで、操作感の確認が主目的でした。
凝ったことはしていない代わりに、ノード(アンカーポイント)が多いカーブを整形する場面が出て、ここで一気に印象が上がりました。

Affinityの ノードツール でノードを削除するとき、閉じたカーブを維持したまま自然にポイントを間引ける挙動がかなり良い…!
Illustratorだと状況によってカーブが途切れたり、意図と違う抜け方をしたりして「アンカーポイントの掃除しんどいな…」となることもあるのですが、Affinityは削除の応答が素直でテンポ良く整形できる印象でした👍

ポイント(ノード)削除挙動の違い

右クリックの「カーブに合わせる—ノードを削除」的なオプションも、削除後のラインを自然に再形成してくれて、ノード多めのデータではかなり助かりそう。

ノード編集に入ると編集対象のノードが前に出て見えるモードに切り替わるので、「いま何を触ってるか」が直感的に分かりやすいのも良かったです。
このノード編集のモードは、Figmaベクター編集しているときの空気にちょっと近く、扱いやすさにつながってる感じがしました。

ちょっと違った所

一方で、Illustratorと感覚が違うなと思ったのは移動まわりです。
グループ化していない複数オブジェクトをまとめて移動したい時に、ドラッグの起点を意識しないと「あれ全部動いてない…」みたいな違和感が出やすかったです。

起点以外をドラッグしても反応しないので、起点オブジェクトをドラッグする必要がある
Illustratorの感覚でラフに触ると最初はハマりやすいポイントなので、ここは慣れポイントとして覚えておくとよさそうです!

まとめ

総合すると、Affinity Designerでも大きな違和感はなく使えそうでした。
特にパス編集の土台がしっかりしていて、ノード整形を気持ちよくやれるツールだな、という発見が大きかったです。

ローカルで安定して起動して普通に作れることの価値を改めて感じましたし、その価値観にAffinityは合っていそうだなと感じています

今すぐ本格的に業務へ置き換える段階ではありませんが、画像とベクターを同時に扱える面白さもあるので、小さいクリエイティブから試験的に混ぜ込みつつ、これからもテストしていくつもりです✨

アドベントカレンダーは明日以降も社内メンバーで続くので、明日以降の記事もお楽しみに〜🎅