- Nuxt
Nuxt 4 入門|作成からビルドまで実行ログと構成図で解説
Nuxt 4とは、Vue 3 をベースに、ページのルーティング・サーバー側の描画(SSR)・APIサーバーまでをまとめて扱えるフレームワークの最新メジャー版です。 2025年7月に 4.0 が公開され、2026年9月28日時点の最新は 4.5.2 です。Nuxt 3 は2026年7月31日にサポートを終えたため、これから始めるなら Nuxt 4 が出発点になります。
この記事では、実際に npm create nuxt@latest でプロジェクトを作り、ページ・レイアウト・API・エラーページを足して、ビルドとプレビューまで行った実行ログをそのまま載せています。app/ 構成のツリーとディレクトリの役割表、よく出るエラー3つ(Nodeのバージョン不足、ハイドレーション不一致、自動インポートが効かない)の再現と直し方も、実行結果つきでまとめました。
Nuxt 4 入門の早見表
| やりたいこと | 置き場所・使うもの | ひとこと |
|---|---|---|
| プロジェクトを作る | npm create nuxt@latest <名前> |
Node.js 22.19 以上(または 24.11 以上)が必要 |
| ページを増やす | app/pages/about.vue |
ファイル名がそのままURL(/about) |
| URLの一部を受け取る | app/pages/items/[id].vue |
useRoute().params.id で取得 |
| ページ間を移動する | <NuxtLink to="/about"> |
ページを再読み込みせずに切り替え |
| 共通の枠(ヘッダー等) | app/layouts/default.vue |
definePageMeta({ layout: 'plain' }) で切り替え |
| 部品を作る | app/components/AppCounter.vue |
import 不要で <AppCounter /> と書ける |
| 処理をまとめる | app/composables/useCounter.ts |
import 不要で useCounter() と呼べる |
| ページ間で状態を共有 | useState('key', () => 初期値) |
SSRとブラウザで値が引き継がれる |
| APIを作る | server/api/hello.get.ts |
/api/hello で呼べる |
| クライアントとサーバーで共通の関数 | shared/utils/format.ts |
両方で自動インポートされる |
| データを取得する | useFetch('/api/hello') |
SSRで取得した値をブラウザへ引き継ぐ |
| ページに入る前の確認 | app/middleware/auth.ts |
navigateTo() でリダイレクト |
| エラー画面 | app/error.vue |
createError() で表示 |
| 設定を変える | nuxt.config.ts |
defineNuxtConfig({...}) |
| 本番ビルド・確認 | npm run build → node .output/server/index.mjs |
.output/ に出力 |
| 静的サイトとして出力 | npm run generate |
.output/public を静的ホスティングへ |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Nuxt 4 入門|作成からビルドまで実行ログと構成図で解説」
Nuxt 4 の動作環境と最新版
Nuxt 4.5.2 は Node.js ^22.19.0 || ^24.11.0 || >=26.0.0 が必要です(nuxt パッケージの engines で確認)。今回の検証環境のバージョンは次のとおりです。
| 項目 | バージョン(2026-09-28) |
|---|---|
| nuxt | 4.5.2 |
| Nitro(サーバーエンジン) | 2.13.4 |
| Vite | 8.3.1 |
| Vue | 3.5.43 |
| vue-router | 5.3.1 |
| Node.js | 22.22.2 |
公式のリリース予定では、Nuxt 5 は2026年第4四半期(予定)、Nuxt 4 のサポートは Nuxt 5 公開から6か月後までとされています。
プロジェクトを作成する(実行ログ)
npm create nuxt@latest にオプションを付けると、質問なしで作成できます。 --template minimal は最小構成のテンプレートです。
npm create nuxt@latest my-nuxt-app -- --template minimal --packageManager npm --no-modules
実行ログです(進行中の表示を省き、結果の行だけ残しています)。
Welcome to Nuxt!
o Creating project in my-nuxt-app
o Downloaded minimal template
o Dependencies installed
o Git repository initialized
— ✨ Nuxt project has been created with the minimal template.
› cd my-nuxt-app
› npm run dev
作成直後の package.json と nuxt.config.ts です。
{
"name": "my-nuxt-app",
"type": "module",
"private": true,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"nuxt": "^4.5.2",
"vue": "^3.5.43",
"vue-router": "^5.3.1"
}
}
// nuxt.config.ts(作成直後)
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true }
})
npm run dev で開発サーバーが起動します(今回はポートを指定)。
$ npx nuxt dev --port 7442
• Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.3.1 and Vue 3.5.43)
➜ Local: http://localhost:7442/
➜ Network: use --host to expose
➜ DevTools: press Shift + Alt + D in the browser (v3.4.2)
√ Vite client built in 168ms
√ Vite server built in 157ms
[nitro] √ Nuxt Nitro server built in 2392ms
ディレクトリ構成と役割
Nuxt 4 では、画面側のコードは app/、サーバー側は server/、両方で使うコードは shared/ に置きます。 この記事のサンプルを作り終えた時点のツリーです。
.
|-- app
| |-- app.vue
| |-- components
| | |-- AppCounter.vue
| | `-- base
| | `-- BaseButton.vue
| |-- composables
| | |-- cart
| | | `-- useCart.ts
| | `-- useCounter.ts
| |-- error.vue
| |-- layouts
| | |-- default.vue
| | `-- plain.vue
| |-- middleware
| | `-- auth.ts
| |-- pages
| | |-- about.vue
| | |-- admin.vue
| | |-- cart.vue
| | |-- clock.vue
| | |-- index.vue
| | `-- items
| | `-- [id].vue
| `-- plugins
| `-- hello.ts
|-- nuxt.config.ts
|-- package.json
|-- public
| |-- favicon.ico
| `-- robots.txt
|-- server
| `-- api
| `-- hello.get.ts
|-- shared
| `-- utils
| `-- format.ts
`-- tsconfig.json
| ディレクトリ・ファイル | 役割 | 自動インポート |
|---|---|---|
app/app.vue |
アプリ全体の入口。<NuxtLayout> と <NuxtPage> を置く |
- |
app/pages/ |
ページ。ファイルの場所がURLになる | - |
app/layouts/ |
ヘッダーなど、ページを包む共通の枠 | - |
app/components/ |
部品。フォルダ名が名前の先頭に付く(base/BaseButton.vue → <BaseButton>) |
○(サブフォルダも対象) |
app/composables/ |
useXxx 形式の処理 |
○(直下のファイルのみ) |
app/utils/ |
画面側の便利関数 | ○(直下のファイルのみ) |
app/middleware/ |
ページ移動の前に動く処理 | - |
app/plugins/ |
アプリ起動時に一度動く処理 | -(自動で登録) |
app/error.vue |
エラー画面 | - |
server/api/ |
APIの処理。/api/... で公開 |
○(server/utils など) |
server/routes/ |
/api 以外のURLのサーバー処理 |
- |
shared/utils/・shared/types/ |
画面とサーバーの両方で使うコード | ○ |
public/ |
そのまま配信するファイル(/robots.txt など) |
- |
nuxt.config.ts |
全体の設定 | - |
~ は app/ を指します(Nuxt 4 の変更点)。tsconfig.json は .nuxt/tsconfig.app.json・server・shared・node の4つを参照する形になっており、画面側とサーバー側で型チェックの設定が分かれています。
ページとルーティング(ファイルベースルーティング)
app/pages/ にファイルを置くだけで、URLとページが対応します。 [id] のように角かっこで囲むと、URLの一部を受け取れます。
<!-- app/app.vue -->
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
<!-- app/pages/items/[id].vue -->
<script setup lang="ts">
const route = useRoute()
const id = Number(route.params.id)
if (!Number.isInteger(id) || id < 1) {
throw createError({ statusCode: 404, statusMessage: '商品が見つかりません' })
}
</script>
<template>
<h1>商品 {{ id }} の詳細</h1>
</template>
| ファイル | URL |
|---|---|
pages/index.vue |
/ |
pages/about.vue |
/about |
pages/items/[id].vue |
/items/1、/items/2 … |
pages/[...slug].vue |
どのURLにも当てはまる受け皿 |
レイアウトで共通の枠を作る
app/layouts/default.vue がすべてのページの既定の枠になり、<slot /> の位置にページが入ります。
<!-- app/layouts/default.vue -->
<template>
<div>
<header>
<NuxtLink to="/">ホーム</NuxtLink> |
<NuxtLink to="/about">概要</NuxtLink> |
<NuxtLink to="/items/1">商品1</NuxtLink>
</header>
<main>
<slot />
</main>
</div>
</template>
別の枠を使うページでは definePageMeta で指定します。
<!-- app/pages/about.vue -->
<script setup lang="ts">
definePageMeta({ layout: 'plain' })
useHead({ title: '概要' })
const { count } = useCounter()
</script>
<template>
<div>
<h1>概要(plainレイアウト)</h1>
<p id="count">ホームで押した回数: {{ count }}</p>
<NuxtLink to="/">ホームへ戻る</NuxtLink>
</div>
</template>
自動インポートを使う
Nuxt では、ref・useRoute などの関数、components/ の部品、composables/ の関数を import 文なしで使えます。
// app/composables/useCounter.ts
export function useCounter() {
// useState:キーごとにSSRとブラウザで共有される状態
const count = useState('counter', () => 0)
const increment = () => count.value++
return { count, increment }
}
<!-- app/components/AppCounter.vue:useCounter も BaseButton も import していない -->
<script setup lang="ts">
const { count, increment } = useCounter()
</script>
<template>
<BaseButton @click="increment">カウント: {{ count }}</BaseButton>
</template>
// shared/utils/format.ts:画面とサーバーの両方で使える
export function formatPrice(value: number) {
return `${value.toLocaleString('ja-JP')}円`
}
useState でページ間の状態を共有する
useState は、キーごとに1つの値をアプリ全体で共有し、SSRで決めた値をブラウザへ引き継ぐ仕組みです。 Vue の ref をモジュールの外側に置く書き方と違い、サーバー上で別の利用者と値が混ざらないように作られています。
Playwright でホームのボタンを2回押し、<NuxtLink> で概要ページへ移動した結果です。
ホーム: カウント: 2
概要: ホームで押した回数: 2
別のページ・別のレイアウトでも、同じキー 'counter' の値が引き継がれました。
データ取得の基本(useFetch)
画面の表示に使うデータは useFetch で取得するのが基本です。 SSRで取得した結果がHTMLと一緒にブラウザへ渡るため、ブラウザで同じAPIをもう一度呼ばずに済みます。useAsyncData との違いや、$fetch を直接使ったときのリクエスト回数の検証は、長くなるため別の記事で詳しく扱います。
// server/api/hello.get.ts
export default defineEventHandler(() => {
return { message: 'こんにちは、Nuxt 4', price: formatPrice(1980) }
})
<!-- app/pages/index.vue -->
<script setup lang="ts">
const { data } = await useFetch('/api/hello')
useHead({ title: 'ホーム' })
const { $hello } = useNuxtApp()
</script>
<template>
<div>
<h1>ホーム</h1>
<p id="msg">{{ data?.message }}({{ data?.price }})</p>
<p id="hello">{{ $hello('Nuxt') }}</p>
<AppCounter />
</div>
</template>
server/api/hello.get.ts のように .get を付けると GET だけを受け付けます。 サーバー側でも shared/utils の formatPrice が import なしで使えています。
ミドルウェアとプラグイン
ミドルウェアはページ移動の前に動く処理、プラグインはアプリ起動時に一度だけ動く処理です。
// app/middleware/auth.ts(名前付きミドルウェア)
export default defineNuxtRouteMiddleware(() => {
const loggedIn = useState('loggedIn', () => false)
if (!loggedIn.value) {
return navigateTo('/about')
}
})
<!-- app/pages/admin.vue -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
</script>
<template>
<h1>管理画面</h1>
</template>
// app/plugins/hello.ts:provide した関数は useNuxtApp().$hello で使える
export default defineNuxtPlugin(() => {
return {
provide: {
hello: (name: string) => `Hello, ${name}!`,
},
}
})
エラーページを用意する
app/error.vue を置くと、404や500のときにこの画面が表示されます。 clearError でエラーを消して別のページへ移れます。
<!-- app/error.vue -->
<script setup lang="ts">
import type { NuxtError } from '#app'
const props = defineProps<{ error: NuxtError }>()
const handleClear = () => clearError({ redirect: '/' })
</script>
<template>
<div>
<h1>{{ props.error.statusCode }} エラー</h1>
<p>{{ props.error.statusMessage }}</p>
<button @click="handleClear">ホームへ戻る</button>
</div>
</template>
ビルドとプレビュー(実行ログ)
npm run build で本番用のファイルが .output/ に作られ、node .output/server/index.mjs で起動できます。
$ npm run build
T Building Nuxt for production...
• Nuxt 4.5.2 (with Nitro 2.13.4, Vite 8.3.1 and Vue 3.5.43)
• Nitro preset: node-server
i Building client...
√ Client built in 3033ms
i Building server...
√ Server built in 475ms
[nitro] √ Generated public .output/public
[nitro] i Building Nuxt Nitro server (preset: node-server, compatibility date: 2025-07-15)
(出力ファイル一覧は省略)
Σ Total size: 2.12 MB (539 kB gzip)
[nitro] √ You can preview this build using node .output/server/index.mjs
— ✨ Build complete!
PORT=7441 node .output/server/index.mjs
# Listening on http://0.0.0.0:7441
起動したサーバーに curl でアクセスした結果です(HTMLから <title> と見出しを抜き出しています)。
| URL | ステータス | 結果 |
|---|---|---|
/ |
200 | title「ホーム」、「こんにちは、Nuxt 4(1,980円)」「Hello, Nuxt!」 |
/about |
200 | title「概要」、plainレイアウトで表示 |
/items/1 |
200 | 「商品 1 の詳細」 |
/items/abc |
404 | error.vue で「404 エラー/商品が見つかりません」 |
/admin |
302 | ミドルウェアで /about へリダイレクト |
/api/hello |
200 | {"message":"こんにちは、Nuxt 4","price":"1,980円"} |
/items/abc は、Accept: text/html 付き(ブラウザと同じ)なら error.vue のHTML、付けない curl では次のJSONが返りました。
{
"error": true,
"url": "http://localhost:7441/items/abc",
"statusCode": 404,
"statusMessage": "商品が見つかりません",
"message": "商品が見つかりません"
}
静的サイトとして出力する npm run generate では、リンクをたどって各ページがHTMLに書き出されました。
[nitro] i Prerendering 3 initial routes with crawler
[nitro] ├─ /404.html (102ms)
[nitro] ├─ /200.html (101ms)
[nitro] ├─ / (122ms)
[nitro] ├─ /admin (75ms)
[nitro] ├─ /about (82ms)
[nitro] ├─ /items/1 (80ms)
[nitro] i Prerendered 13 routes in 2.587 seconds
[nitro] √ Generated public .output/public
— ✨ You can now deploy .output/public to any static hosting!
nuxt.config.ts の主要設定
| 設定 | 例 | 用途 |
|---|---|---|
compatibilityDate |
'2025-07-15' |
Nitro などの挙動の基準日 |
devtools |
{ enabled: true } |
開発時の Nuxt DevTools |
modules |
['@nuxt/ui'] |
モジュールの追加 |
css |
['~/assets/css/main.css'] |
全体に読み込むCSS |
app.head |
{ title: 'サイト名' } |
全ページ共通の head |
runtimeConfig |
{ apiSecret: '', public: { apiBase: '' } } |
環境変数で上書きできる設定値 |
routeRules |
{ '/about': { prerender: true } } |
URLごとの描画方法やキャッシュ |
ssr |
false |
アプリ全体をSPAにする |
imports.dirs |
['composables/**'] |
自動インポートの対象フォルダを追加 |
future.compatibilityVersion |
5 |
Nuxt 5 向けの変更を先に試す |
SSR・SPA・静的生成の選び方
Nuxt は既定でSSR(リクエストごとにサーバーでHTMLを作る)です。URLごとに描画方法を変えることもできます。 詳しい比較は別の記事で扱います。
| 方式 | 設定 | 向いているページ |
|---|---|---|
| SSR(既定) | そのまま | 検索結果に出したい、内容がよく変わるページ |
| 静的生成(SSG) | npm run generate や routeRules の prerender: true |
会社概要・記事など内容が固定のページ |
| SPA | ssr: false、または routeRules の ssr: false |
ログイン後の管理画面など |
// nuxt.config.ts:URLごとに切り替える例(公式ドキュメントの書き方。本記事では未実行)
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true },
'/admin/**': { ssr: false },
},
})
よくあるエラーと直し方(実際に再現)
Node.js のバージョンが足りない
Node.js 20.20.2 で npm i nuxt@4.5.2 --dry-run を実行すると、まず EBADENGINE の警告が出ます。
npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE package: 'nuxt@4.5.2',
npm warn EBADENGINE required: { node: '^22.19.0 || ^24.11.0 || >=26.0.0' },
npm warn EBADENGINE current: { node: 'v20.20.2', npm: '10.9.7' }
npm warn EBADENGINE }
そのまま Node.js 20 で nuxt build を実行すると、バージョン不足とは読み取りにくいエラーで止まりました。
T Building Nuxt for production...
ERROR webidl.util.markAsUncloneable is not a function
at new CacheStorage (node_modules/undici/lib/web/cache/cachestorage.js:20:17)
at Object.<anonymous> (node_modules/undici/index.js:179:25)
直し方:node -v で確認し、Node.js 22.19 以上(または 24.11 以上)に上げます。 同じプロジェクトを Node.js 22.22.2 で実行すると、ビルドは成功しました。
ハイドレーション不一致(Hydration mismatch)
ハイドレーションとは、SSRで作ったHTMLにブラウザ側のVueがつながる処理です。 サーバーとブラウザで表示内容が違うと警告が出ます。時刻を表示するページで再現しました。
<!-- 直す前:app/pages/clock.vue -->
<script setup lang="ts">
const now = Date.now()
</script>
<template>
<p>表示した時刻: {{ now }}</p>
</template>
開発サーバーでページを開いたときの、ブラウザのコンソールです。
[Vue warn]: Hydration text content mismatch on
- rendered on server: 表示した時刻: 1790678280916
- expected on client: 表示した時刻: 1790678283576
at <Clock onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > >
Hydration completed but contains mismatches.
<!-- 直した後:サーバーで決めた値を useState でブラウザへ引き継ぐ -->
<script setup lang="ts">
const now = useState('now', () => Date.now())
</script>
<template>
<p>表示した時刻: {{ now }}</p>
</template>
直した後は、警告が出なくなりました。 ブラウザだけで決めたい値(画面幅など)は、onMounted の中で設定するか、<ClientOnly> で囲む方法もあります。
自動インポートが効かない
composables/ の自動インポートは、直下のファイルだけが対象です。 app/composables/cart/useCart.ts に置いた関数を使うと、ページが500エラーになりました。
{
"statusCode": 500,
"statusMessage": "Server Error",
"message": "useCart is not defined",
...
}
直し方:nuxt.config.ts の imports.dirs にフォルダを追加します。
// nuxt.config.ts
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
imports: {
// composables/ の下のフォルダも自動インポートの対象にする
dirs: ['composables/**'],
},
})
設定後、/cart は200で「カートの件数: 0」と表示されました。直下の composables/index.ts から export { useCart } from './cart/useCart' と書き出す方法でも対応できます。
| エラー・警告 | よくある原因 | 直し方 |
|---|---|---|
EBADENGINE、markAsUncloneable is not a function |
Node.js が要件より古い | Node.js 22.19 以上 / 24.11 以上へ |
Hydration ... mismatch |
時刻・乱数・ブラウザだけの値を表示 | useState、onMounted、<ClientOnly> |
xxx is not defined |
サブフォルダに置いた composable | imports.dirs に追加、または直下で再エクスポート |
Nuxt 3 との違い
公式のアップグレードガイドで確認した主な違いです。
| 項目 | Nuxt 3 | Nuxt 4 |
|---|---|---|
| 画面側コードの場所 | プロジェクト直下(pages/ など) |
app/(app/pages/ など) |
~ の指す場所 |
プロジェクト直下 | app/ |
| server の場所 | <srcDir>/server |
プロジェクト直下の server/ |
| 共有コード | なし | shared/(shared/utils・shared/types は自動インポート) |
| TypeScript の設定 | 1つの tsconfig | app・server・shared・node に分割 |
useFetch の data |
深いリアクティブな ref |
shallowRef(deep: true で変更可) |
data・error の初期値 |
null |
undefined |
同じキーの useAsyncData |
個別に持つ | data・error・status を共有 |
useHead の内部 |
Unhead v1 | Unhead v2 |
| サポート | 2026-07-31 で終了 | 現行(Nuxt 5 公開から6か月後まで) |
旧構成(直下に pages/ がある状態)も検出されれば動くため、段階的に移行できます。
Nuxt 5 への見通し
公式ロードマップでは、Nuxt 5 は2026年第4四半期(予定)で、Nitro v3 への更新が中心とされています。4.5.2 には future.compatibilityVersion: 5 があり、Nuxt 5 向けの変更を先に試せます。今回のサンプルに設定して nuxt build を実行したところ、ビルドは成功しました(この時点のサーバーエンジンは Nitro 2.13.4)。
export default defineNuxtConfig({
future: { compatibilityVersion: 5 },
})
Next.js との対応表
| Nuxt 4 | Next.js(App Router) |
|---|---|
app/pages/about.vue |
app/about/page.tsx |
app/layouts/default.vue |
app/layout.tsx |
server/api/hello.get.ts |
app/api/hello/route.ts |
app/middleware/ |
proxy.ts |
app/error.vue |
error.tsx・not-found.tsx |
よくある質問
Q. 今から始めるなら Nuxt 3 と Nuxt 4 のどちらですか? A. Nuxt 4 です。Nuxt 3 は2026年7月31日でサポートを終えています。Nuxt 5 が出たあとも、Nuxt 4 は6か月間サポートされる予定です。
Q. Nuxt 3 のプロジェクトは app/ に移さないと動きませんか?
A. 旧構成のままでも動きます。公式のアップグレードガイドに沿って、データ取得の挙動の違い(shallowRef、初期値 undefined など)から確認していくと進めやすくなります。
Q. useState と Pinia はどう使い分けますか?
A. 少しの値を共有するだけなら useState、状態を操作する処理が多い場合は Pinia(@pinia/nuxt)が向いています。
Q. 自動インポートを使わずに import を書いてもよいですか?
A. 書いても動きます。#imports から明示的に import することもできます。
まとめ
- Nuxt 4(4.5.2)は Node.js 22.19 以上 / 24.11 以上で動きます。古いと分かりにくいエラーになります。
- 画面は
app/、APIはserver/、共通コードはshared/に置きます。 - ページ・レイアウト・部品・composable はファイルを置くだけで使えます。
- 状態共有は
useState。SSRで決めた値がブラウザへ引き継がれます。 - ハイドレーション不一致は
useStateなどで値をそろえると解消できます。 - サブフォルダの composable は
imports.dirsで自動インポートの対象にできます。 - Nuxt 5 は2026年第4四半期予定。
future.compatibilityVersion: 5で先に試せます。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Nuxt 4 入門|作成からビルドまで実行ログと構成図で解説」
株式会社RJCでは、新しいフレームワークを実際に動かしながら理解する進め方を、プロジェクトの中で仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。