Add Sanity Studio served at /studio via Docker multi-stage build
Builds studio/ separately during Docker build and copies output to public/studio/ so it is served as static files by the Astro Node adapter. Catch-all route redirects deep studio links back to /studio for SPA routing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fc644510af
commit
9ca50a1da8
8 changed files with 15357 additions and 291 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -1,5 +1,12 @@
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
|
public/studio
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
studio/.env
|
||||||
|
studio/.env.local
|
||||||
|
studio/.sanity
|
||||||
.DS_Store
|
.DS_Store
|
||||||
server/public
|
server/public
|
||||||
vite.config.ts.*
|
vite.config.ts.*
|
||||||
|
|
|
||||||
45
Dockerfile
Normal file
45
Dockerfile
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
FROM node:20-alpine AS base
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# ── 1. Install main project deps ─────────────────────────────────────────────
|
||||||
|
FROM base AS deps
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# ── 2. Install studio deps ────────────────────────────────────────────────────
|
||||||
|
FROM base AS studio-deps
|
||||||
|
COPY studio/package.json studio/package-lock.json* ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# ── 3. Build Sanity Studio ────────────────────────────────────────────────────
|
||||||
|
FROM base AS studio-build
|
||||||
|
COPY --from=studio-deps /app/node_modules ./node_modules
|
||||||
|
COPY studio/ ./
|
||||||
|
ARG SANITY_STUDIO_PROJECT_ID
|
||||||
|
ARG SANITY_STUDIO_DATASET=production
|
||||||
|
ENV SANITY_STUDIO_PROJECT_ID=$SANITY_STUDIO_PROJECT_ID
|
||||||
|
ENV SANITY_STUDIO_DATASET=$SANITY_STUDIO_DATASET
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ── 4. Build Astro site (with studio output as static files) ──────────────────
|
||||||
|
FROM base AS build
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
COPY --from=studio-build /app/dist ./public/studio
|
||||||
|
ARG SANITY_PROJECT_ID
|
||||||
|
ARG SANITY_DATASET=production
|
||||||
|
ARG SANITY_API_TOKEN
|
||||||
|
ENV SANITY_PROJECT_ID=$SANITY_PROJECT_ID
|
||||||
|
ENV SANITY_DATASET=$SANITY_DATASET
|
||||||
|
ENV SANITY_API_TOKEN=$SANITY_API_TOKEN
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ── 5. Runtime ────────────────────────────────────────────────────────────────
|
||||||
|
FROM node:20-alpine AS runtime
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=build /app/dist ./dist
|
||||||
|
COPY --from=build /app/node_modules ./node_modules
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
|
ENV PORT=4321
|
||||||
|
EXPOSE 4321
|
||||||
|
CMD ["node", "./dist/server/entry.mjs"]
|
||||||
1176
package-lock.json
generated
1176
package-lock.json
generated
File diff suppressed because it is too large
Load diff
7
src/pages/studio/[...path].ts
Normal file
7
src/pages/studio/[...path].ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type { APIRoute } from "astro";
|
||||||
|
|
||||||
|
// Redirect deep studio links (e.g. /studio/desk/post) back to /studio so the
|
||||||
|
// SPA can boot and handle its own routing. Static assets under /studio/assets/*
|
||||||
|
// are served before this route ever fires.
|
||||||
|
export const GET: APIRoute = () =>
|
||||||
|
new Response(null, { status: 302, headers: { Location: "/studio" } });
|
||||||
6
studio/.env.example
Normal file
6
studio/.env.example
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# ── Sanity Studio ────────────────────────────────────────────────────────────
|
||||||
|
# Copy to .env and fill in your values from https://www.sanity.io/manage
|
||||||
|
# SANITY_STUDIO_ prefix is required — Sanity injects these into the studio bundle.
|
||||||
|
|
||||||
|
SANITY_STUDIO_PROJECT_ID=
|
||||||
|
SANITY_STUDIO_DATASET=production
|
||||||
14402
studio/package-lock.json
generated
Normal file
14402
studio/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"sanity": "^3.66.0"
|
"sanity": "^3.66.0",
|
||||||
|
"styled-components": "^6.4.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { defineConfig } from 'sanity';
|
import { defineConfig } from 'sanity';
|
||||||
import { structureTool } from 'sanity/structure';
|
import { structureTool } from 'sanity/structure';
|
||||||
import { visionTool } from '@sanity/vision';
|
|
||||||
import { schemaTypes } from './schemaTypes';
|
import { schemaTypes } from './schemaTypes';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
|
@ -13,7 +12,6 @@ export default defineConfig({
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
structureTool(),
|
structureTool(),
|
||||||
visionTool(), // GROQ query playground — remove in production if desired
|
|
||||||
],
|
],
|
||||||
|
|
||||||
schema: {
|
schema: {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue