diff --git a/.changeset/early-pens-itch.md b/.changeset/early-pens-itch.md
new file mode 100644
index 0000000..6a1fb6c
--- /dev/null
+++ b/.changeset/early-pens-itch.md
@@ -0,0 +1,7 @@
+---
+"@inkathon/frontend": minor
+"@inkathon/contracts": minor
+---
+
+- Setup Docker workflow for local development of frontend (Next.js Startup & Watching) and production build (non-Vercel deployments)
+- Setup Docker workflow for local development of contracts (Rust & Substrate Contracts Node Setup, Contract Deployment)
diff --git a/Dockerfile.contracts b/Dockerfile.contracts
new file mode 100644
index 0000000..a4034d5
--- /dev/null
+++ b/Dockerfile.contracts
@@ -0,0 +1,48 @@
+FROM paritytech/ci-linux:production as builder
+
+WORKDIR /app
+COPY . .
+
+# Switch from sh to bash
+RUN rm /bin/sh && ln -s /bin/bash /bin/sh
+
+RUN apt update
+
+RUN echo "**Getting Ubuntu and Rust dependencies**"
+RUN apt install -y build-essential pkg-config git clang curl libssl-dev llvm libudev-dev
+
+RUN echo "**Installing node.js, pnpm, and package dependencies**"
+# Install nvm and node
+RUN mkdir -p /usr/local/nvm
+ENV NVM_DIR /usr/local/nvm
+ENV NODE_VERSION v20.9.0
+RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
+RUN /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION && nvm use --delete-prefix $NODE_VERSION"
+ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/bin
+ENV PATH $NODE_PATH:$PATH
+# Install pnpm
+RUN npm i --global --no-update-notifier --no-fund pnpm@8
+RUN yes Y | pnpm install
+
+RUN echo "*** Instaling Rust environment for contracts node***"
+RUN rm -rf /usr/local/rustup /usr/local/cargo
+RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly
+ENV PATH="/root/.cargo/bin:${PATH}"
+RUN rustup default stable
+RUN rustup update
+RUN rustup target add wasm32-unknown-unknown
+RUN rustup update nightly
+RUN rustup target add wasm32-unknown-unknown --toolchain nightly
+RUN rustup show
+RUN rustup +nightly show
+RUN cargo install contracts-node
+
+RUN echo "*** Installing cargo-contract ***"
+RUN rustup component add rust-src
+RUN cargo install --force --locked cargo-contract
+
+# Set and expose the port that the app will run on
+EXPOSE 9944
+
+# RUN echo "*** Start Substrate node template ***"
+CMD [ "/usr/local/cargo/bin/substrate-contracts-node", "--dev", "--rpc-cors=all"]
\ No newline at end of file
diff --git a/Dockerfile.frontend b/Dockerfile.frontend
new file mode 100644
index 0000000..ba8a909
--- /dev/null
+++ b/Dockerfile.frontend
@@ -0,0 +1,58 @@
+# Inspired by https://www.darraghoriordan.com/2023/04/13/running-next-js-docker-container
+# STAGE 1: A container with pnpm and python3 is required
+FROM node:18-alpine as pnpm_base
+
+WORKDIR /app
+# install pnpm
+RUN npm i --global --no-update-notifier --no-fund pnpm@8 \
+# install python3 and other deps
+ && apk add --no-cache g++=~13.2.1_git20231014-r0 make=~4.4.1-r2 py3-pip libc6-compat bash=~5.2.21-r0
+
+
+# STAGE 2: fetch deps into the pnpm store
+# We run pnpm fetch in a separate step to avoid re-fetching deps on every code change
+FROM pnpm_base as fetched_deps
+WORKDIR /app
+# setting env to production usually speeds up installations
+ENV NODE_ENV=production
+COPY pnpm-lock.yaml ./
+# set the store dir to a folder that is not in the project
+RUN pnpm config set store-dir /workdir/.pnpm-store \
+ && pnpm fetch
+
+# STAGE 3: Copy the application code and install all deps from cache into the application
+FROM fetched_deps as with_all_deps
+# Copy whole project since it's using monorepo
+COPY . ./
+# Install all the deps
+RUN pnpm install --offline
+
+# STAGE 4: Build the NextJS app
+# Use pnpm filter to only build the frontend app
+# Then use pnpm deploy command to prune the dependencies
+FROM with_all_deps as builder
+RUN pnpm --filter='*frontend' build \
+ && pnpm --filter='*frontend' deploy pruned --prod
+
+# STAGE 5: Create a clean production image - only take pruned assets
+FROM node:18-alpine AS runner
+WORKDIR /app
+# We set the NODE_ENV to production to make sure that the app runs in production mode
+ENV NODE_ENV=production
+# We add a non-root user to run the app for security reasons
+RUN addgroup --system --gid 1001 app \
+ && adduser --system --uid 1001 app
+USER app
+
+# Copy the built app assets from the builder stage
+# NextJS produces a backend server and a frontend app
+COPY --chown=app:app --from=builder /app/frontend/.next/standalone src/
+COPY --chown=app:app --from=builder /app/frontend/public src/frontend/public
+COPY --chown=app:app --from=builder /app/frontend/.next/static src/frontend/.next/static
+
+# Set and expose the port that the app will run on
+ENV PORT 3000
+EXPOSE 3000
+
+# Run the app
+CMD ["node", "src/frontend/server.js"]
diff --git a/README.md b/README.md
index 8fa849c..fc83511 100644
--- a/README.md
+++ b/README.md
@@ -187,29 +187,9 @@ Spinning up a deployment via Vercel is pretty straightforward as the necessary s
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnext.js%2Ftree%2Fcanary%2Fexamples%2Fhello-world&env=NEXT_PUBLIC_DEFAULT_CHAIN&envDescription=Insert%20%60alephzero-testnet%60%20or%20%60shibuya%60&envLink=https%3A%2F%2Fgithub.com%2Fscio-labs%2Finkathon%23environment-variables&project-name=inkathon&repository-name=inkathon&redirect-url=https%3A%2F%2Fgithub.com%2Fscio-labs%2Finkathon&demo-url=https%3A%2F%2Finkathon.xyz)
-### Environment Variables
-
-One key element making this boilerplate so flexible is the usage of environment variables to configure the active network in the frontend. This is done by setting the `NEXT_PUBLIC_DEFAULT_CHAIN` variable in the `frontend/.env.local` file, or in the Vercel deployment settings respectively.
-
-
-All Supported Chain Constants
-
-| Network Identifier | Name | Type |
-| ------------------- | ----------------------- | ------- |
-| `development` | ️Local Development Node | Testnet |
-| `alephzero-testnet` | Aleph Zero Testnet | Testnet |
-| `rococo` | Rococo | Testnet |
-| `shibuya` | Shibuya Testnet | Testnet |
-| `shiden` | Shiden | Mainnet |
-| `alephzero` | Aleph Zero | Mainnet |
-| `astar` | Astar | Mainnet |
-
-Source: https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts
-
-> [!NOTE]
-> Chains can also be supplied manually by creating a [`SubstrateChain`](https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts#L4) object. If you think a chain is missing, please open an issue or PR.
+Alternatively, you can also use the provided Dockerfiles to deploy to any hosting provider of your choice. Read more [here](https://github.com/scio-labs/inkathon/pull/50#issue-2041934251).
-
+### Environment Variables
All environment variables are imported from `process.env` in [`frontend/src/config/environment.ts`](https://github.com/scio-labs/inkathon/blob/main/frontend/src/config/environment.ts) and re-exported from there. For improved type safety, Always only import environment variables from `@/config/environment` and never directly from `process.env`.
@@ -222,6 +202,15 @@ All environment variables are imported from `process.env` in [`frontend/src/conf
\*️⃣ Required
+#### Supported Chains
+
+One key element making this boilerplate so flexible is the usage of environment variables to configure the active network in the frontend. This is done by setting the `NEXT_PUBLIC_DEFAULT_CHAIN` variable in the `frontend/.env.local` file, or in the deployment settings respectively.
+
+If your network is not provided by the `use-inkathon` library, you can add it manually by creating a new [`SubstrateChain`](https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts#L4) object. If you think a chain is missing, please open an issue or PR.
+
+> [!IMPORTANT]
+> All supported chain constants [can be found here](https://github.com/scio-labs/use-inkathon/blob/main/src/chains.ts) in the `scio-labs/use-inkathon` repository.
+
### Contract Deployment
In the [Getting Started](#getting-started) section above, we've already deployed the sample `Greeter` contract on a local node. To target a live network, we can use the `CHAIN` environment variable when running the `deploy` script.
diff --git a/docker-compose.contracts.yaml b/docker-compose.contracts.yaml
new file mode 100644
index 0000000..57b80d6
--- /dev/null
+++ b/docker-compose.contracts.yaml
@@ -0,0 +1,11 @@
+version: '1.0'
+
+services:
+ substrate-contracts-node:
+ build:
+ context: .
+ dockerfile: Dockerfile.contracts
+ image: contracts-node:latest
+ container_name: substrate-contracts-node
+ ports:
+ - "9944:9944"
\ No newline at end of file
diff --git a/docker-compose.frontend.yaml b/docker-compose.frontend.yaml
new file mode 100644
index 0000000..9156986
--- /dev/null
+++ b/docker-compose.frontend.yaml
@@ -0,0 +1,29 @@
+version: '1.0'
+services:
+ frontend-dev:
+ container_name: inkathon-frontend-dev
+ build:
+ context: .
+ dockerfile: Dockerfile.frontend
+ target: with_all_deps
+ restart: always
+ command: pnpm run dev
+ environment:
+ - NODE_ENV=development
+ - CHOKIDAR_USEPOLLING=true
+ - WATCHPACK_POLLING=true
+ volumes:
+ - .:/app
+ - /app/node_modules
+ - /app/.next
+ ports:
+ - 3000:3000
+ frontend-prod:
+ container_name: inkathon-frontend-prod
+ build:
+ context: .
+ dockerfile: Dockerfile.frontend
+ args:
+ - NODE_ENV=production
+ ports:
+ - 3001:3000
\ No newline at end of file
diff --git a/frontend/next.config.js b/frontend/next.config.js
index 933fb15..23d0d80 100644
--- a/frontend/next.config.js
+++ b/frontend/next.config.js
@@ -2,6 +2,8 @@
/* eslint-env node */
// @ts-check
+const path = require('path')
+
/**
* @type {import('next').NextConfig}
**/
@@ -10,6 +12,7 @@ const nextConfig = {
// Fix for warnings about cjs/esm package duplication
// See: https://github.com/polkadot-js/api/issues/5636
transpilePackages: ['@polkadot/.*'],
+ output: 'standalone',
}
module.exports = nextConfig