-
Notifications
You must be signed in to change notification settings - Fork 0
Staging #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Staging #63
Changes from all commits
d01753b
fc3cf26
f802e39
6cad625
dbfaee6
4adaac4
21cc8f0
3a6cc47
f7504c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| Dockerfile | ||
| .dockerignore | ||
| node_modules | ||
| npm-debug.log | ||
| README.md | ||
| .next | ||
| .git | ||
| .env* | ||
| !.env.example | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| name: SystemCraft CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ "main" ] | ||
| pull_request: | ||
| branches: [ "main" ] | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| lint-and-typecheck: | ||
| name: Lint & Typecheck | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| cache: 'npm' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Run ESLint | ||
| run: npm run lint | ||
|
|
||
| - name: Typecheck | ||
| run: npx tsc --noEmit | ||
|
|
||
| docker-build-test: | ||
| name: Docker Build Test | ||
| runs-on: ubuntu-latest | ||
| needs: [lint-and-typecheck] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
|
|
||
| - name: Build Docker Image | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| push: false # We only want to test the build, not push it to a registry yet | ||
| tags: systemcraft-web:latest | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
| build-args: | | ||
| NEXT_TELEMETRY_DISABLED=1 | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| NEXT_PUBLIC_FIREBASE_API_KEY=${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }} | ||
| NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }} | ||
| NEXT_PUBLIC_FIREBASE_PROJECT_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }} | ||
| NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }} | ||
| NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }} | ||
| NEXT_PUBLIC_FIREBASE_APP_ID=${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,4 +40,5 @@ yarn-error.log* | |
| *.tsbuildinfo | ||
| next-env.d.ts | ||
|
|
||
| docs/ | ||
| docs/ | ||
| eslint_output.txt | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # SystemCraft Docker Guide | ||
|
|
||
| SystemCraft is fully containerized using a highly optimized, multi-stage Next.js Dockerfile constraint to `node:20-alpine`. | ||
|
|
||
| ## Prerequisites | ||
| - [Docker](https://docs.docker.com/get-docker/) installed and running on your local machine. | ||
| - A populated `.env` file in the root directory (copy from `.env.example`). Your Next.js static build requires the `NEXT_PUBLIC_FIREBASE_*` variables to be present during the build process. | ||
|
|
||
| ## Running Locally | ||
|
|
||
| The easiest way to build and run the application is using Docker Compose. | ||
|
|
||
| 1. **Start the application (Builds if necessary):** | ||
| ```bash | ||
| docker-compose up --build -d | ||
| ``` | ||
| *The `-d` flag runs the container in the background (detached mode).* | ||
|
|
||
| 2. **Access the application:** | ||
| Open your browser and navigate to `http://localhost:3000`. | ||
|
|
||
| 3. **Stop the application:** | ||
| ```bash | ||
| docker-compose down | ||
| ``` | ||
|
|
||
| 4. **View live logs:** | ||
| If you ran the container in detached mode, you can still view the server logs: | ||
| ```bash | ||
| docker-compose logs -f | ||
| ``` | ||
|
|
||
| ## Production Architecture Notes | ||
|
|
||
| - **Standalone Mode:** The `next.config.ts` is configured with `output: "standalone"`. This prevents Docker from copying the entire bulk of `node_modules` into the final runner image, drastically saving space. | ||
| - **Environment Variables:** During the `builder` stage, Next.js "bakes" `NEXT_PUBLIC_` variables into the static frontend files. Ensure your `.env` is properly populated before running `docker-compose build`. If you change your `.env` file, you **must rebuild** the image for those changes to take effect on the client side. | ||
| - **Secret Management:** Server-side secrets (like MongoDB connections) are passed at runtime by `docker-compose.yml` reading the local `.env` file. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| FROM node:20-alpine AS base | ||
|
|
||
| FROM base AS deps | ||
|
|
||
| RUN apk add --no-cache libc6-compat | ||
| WORKDIR /app | ||
| COPY package.json package-lock.json* ./ | ||
| RUN npm ci | ||
|
|
||
| FROM base AS builder | ||
| WORKDIR /app | ||
| COPY --from=deps /app/node_modules ./node_modules | ||
| COPY . . | ||
|
|
||
| ARG NEXT_PUBLIC_FIREBASE_API_KEY | ||
| ARG NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN | ||
| ARG NEXT_PUBLIC_FIREBASE_PROJECT_ID | ||
| ARG NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET | ||
| ARG NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID | ||
| ARG NEXT_PUBLIC_FIREBASE_APP_ID | ||
|
|
||
| ENV NEXT_PUBLIC_FIREBASE_API_KEY=$NEXT_PUBLIC_FIREBASE_API_KEY | ||
| ENV NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=$NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN | ||
| ENV NEXT_PUBLIC_FIREBASE_PROJECT_ID=$NEXT_PUBLIC_FIREBASE_PROJECT_ID | ||
| ENV NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=$NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET | ||
| ENV NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=$NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID | ||
| ENV NEXT_PUBLIC_FIREBASE_APP_ID=$NEXT_PUBLIC_FIREBASE_APP_ID | ||
| ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
|
||
| RUN npm run build | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| FROM base AS runner | ||
| WORKDIR /app | ||
|
|
||
| ENV NODE_ENV production | ||
| ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
|
||
| RUN addgroup --system --gid 1001 nodejs | ||
| RUN adduser --system --uid 1001 nextjs | ||
|
|
||
| RUN mkdir .next | ||
| RUN chown nextjs:nodejs .next | ||
|
|
||
| COPY --from=builder /app/public ./public | ||
|
|
||
| COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ | ||
| COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static | ||
| USER nextjs | ||
| EXPOSE 3000 | ||
| ENV PORT 3000 | ||
|
|
||
| ENV HOSTNAME "0.0.0.0" | ||
| CMD ["node", "server.js"] | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -39,7 +39,7 @@ export default function AnalyticsPage() { | |||||
| const [retryCounter, setRetryCounter] = useState(0); | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| if (!isAuthenticated || !user) return; | ||||||
| if (!isAuthenticated || !user?.uid) return; | ||||||
|
|
||||||
| const controller = new AbortController(); | ||||||
|
|
||||||
|
|
@@ -54,8 +54,8 @@ export default function AnalyticsPage() { | |||||
| if (!controller.signal.aborted) { | ||||||
| setData(result); | ||||||
| } | ||||||
| } catch (err: any) { | ||||||
| if (err.name === 'AbortError') return; | ||||||
| } catch (err: unknown) { | ||||||
| if (err instanceof Error && err.name === 'AbortError') return; | ||||||
| console.error(err); | ||||||
| if (!controller.signal.aborted) { | ||||||
| setError(err instanceof Error ? err.message : 'Unknown error'); | ||||||
|
|
@@ -72,7 +72,7 @@ export default function AnalyticsPage() { | |||||
| return () => { | ||||||
| controller.abort(); | ||||||
| }; | ||||||
| }, [isAuthenticated, user?.uid, retryCounter]); | ||||||
| }, [isAuthenticated, user, retryCounter]); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using full The codebase pattern in Using
🐛 Recommended fix- }, [isAuthenticated, user, retryCounter]);
+ }, [isAuthenticated, user?.uid, retryCounter]);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
|
|
||||||
| if (authLoading || isLoading) { | ||||||
| return ( | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| /* eslint-disable */ | ||
| "use client"; | ||
|
|
||
| import React, { useRef, useMemo } from "react"; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| version: '3.8' | ||
| services: | ||
| web: | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile | ||
| ports: | ||
| - "3000:3000" | ||
| env_file: | ||
| - .env | ||
| environment: | ||
| - NODE_ENV=production | ||
| restart: unless-stopped |
Uh oh!
There was an error while loading. Please reload this page.