Deploy a full-stack App
Build a frontend and backend from one repository, with a scoped shared PostgreSQL database.
Read the AI prompt before copying
Help me prepare my existing project for PhotonSpark Webhost using the guide below. Ask for the project requirements and deployment choice when missing. Inspect existing files before editing, preserve behavior and data, and do not invent supported flags or deployment options. Keep credentials out of code and prompts. Explain dashboard settings and test production behavior. Publishing, DNS changes, and destructive actions need my authorization. Report what passed and what remains unverified.
# Deploy a full-stack App
Build a frontend and backend from one repository, with a scoped shared PostgreSQL database.
Source: https://webhost.photonspark.com/docs/apps
## Organize the repository
The standard manifest is platform.app.yaml at the repository root; the manifest path is configurable in Webhost. Frontend buildMode accepts static, node-static, or node-server. Paths are relative to the repository; the Dockerfile path is relative to backend.path.
```text
my-app/
platform.app.yaml
frontend/
package.json
package-lock.json
src/
backend/
Dockerfile
.dockerignore
package.json
package-lock.json
src/
```
## Describe the deployment
This example expects a real npm run migrate script in the backend. Omit migrations if you have no migration command. App deployment currently provisions shared PostgreSQL even if the database block is omitted; omission is not a database-disable switch. Your application may leave the database unused. dedicated-ha is reserved and is not provisioned by this platform version.
```yaml
version: 1
frontend:
path: frontend
buildMode: node-static
backend:
path: backend
dockerfile: Dockerfile
port: 8080
healthPath: /healthz
# Shared PostgreSQL is the current App default. Migrations are optional.
database:
postgres:
tier: shared
migrations:
command: npm run migrate
routing:
apiPrefix: /api
```
## Package the backend
The backend must listen on 0.0.0.0 at backend.port and serve backend.healthPath. routing.apiPrefix must be /api in this platform version. Keep application endpoints under /api; the gateway preserves that prefix. Return a successful response from the configured health route.
Compile TypeScript or other source during the image build. Start the compiled production entry point. Exclude .env, credentials, node_modules, and unrelated files from the Docker build context.
```dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --no-audit --no-fund
COPY --chown=node:node src/ ./src/
ENV NODE_ENV=production HOST=0.0.0.0 PORT=8080
USER node
EXPOSE 8080
CMD ["node", "src/server.js"]
```
## Connect the database and frontend
- The shared PostgreSQL service gives the app a scoped user and schema. Read DATABASE_URL from the backend environment; never commit it or put it in browser code.
- The optional migration command runs separately using the app database credentials. Make migrations safe to retry and consider compatibility with the currently serving application.
- Browser code calls /api on the application's public hostname. Server-rendered frontend code can use process.env.BACKEND_INTERNAL_URL to reach its own backend.
- The backend also receives FRONTEND_INTERNAL_URL. These internal URLs are server-only settings.
- Do not rely on container memory or local files for durable user data. Use PostgreSQL or another explicitly configured persistent service.
## Build, deploy, and verify
A successful build alone does not prove the backend starts or the application works. A Git polling warning can coexist with a healthy older release.
1. Create an App, connect the repository and branch, and select its manifest path.
2. Configure build, frontend, and backend environment values. Keep secrets out of frontend bundles.
3. Run the deployment. Webhost builds the frontend, builds and publishes the backend image, provisions shared PostgreSQL, and runs the configured migration.
4. Inspect build logs and both runtime components. Verify the homepage, backend health route, real API requests, and database behavior through the public hostname.
- [Frontend Site build contracts](https://webhost.photonspark.com/docs/sites)
- [Deployment workflow](https://webhost.photonspark.com/docs/deployments)
Organize the repository
The standard manifest is platform.app.yaml at the repository root; the manifest path is configurable in Webhost. Frontend buildMode accepts static, node-static, or node-server. Paths are relative to the repository; the Dockerfile path is relative to backend.path.
my-app/
platform.app.yaml
frontend/
package.json
package-lock.json
src/
backend/
Dockerfile
.dockerignore
package.json
package-lock.json
src/Describe the deployment
This example expects a real npm run migrate script in the backend. Omit migrations if you have no migration command. App deployment currently provisions shared PostgreSQL even if the database block is omitted; omission is not a database-disable switch. Your application may leave the database unused. dedicated-ha is reserved and is not provisioned by this platform version.
version: 1
frontend:
path: frontend
buildMode: node-static
backend:
path: backend
dockerfile: Dockerfile
port: 8080
healthPath: /healthz
# Shared PostgreSQL is the current App default. Migrations are optional.
database:
postgres:
tier: shared
migrations:
command: npm run migrate
routing:
apiPrefix: /apiPackage the backend
The backend must listen on 0.0.0.0 at backend.port and serve backend.healthPath. routing.apiPrefix must be /api in this platform version. Keep application endpoints under /api; the gateway preserves that prefix. Return a successful response from the configured health route.
Compile TypeScript or other source during the image build. Start the compiled production entry point. Exclude .env, credentials, node_modules, and unrelated files from the Docker build context.
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --no-audit --no-fund
COPY --chown=node:node src/ ./src/
ENV NODE_ENV=production HOST=0.0.0.0 PORT=8080
USER node
EXPOSE 8080
CMD ["node", "src/server.js"]Connect the database and frontend
- The shared PostgreSQL service gives the app a scoped user and schema. Read DATABASE_URL from the backend environment; never commit it or put it in browser code.
- The optional migration command runs separately using the app database credentials. Make migrations safe to retry and consider compatibility with the currently serving application.
- Browser code calls /api on the application's public hostname. Server-rendered frontend code can use process.env.BACKEND_INTERNAL_URL to reach its own backend.
- The backend also receives FRONTEND_INTERNAL_URL. These internal URLs are server-only settings.
- Do not rely on container memory or local files for durable user data. Use PostgreSQL or another explicitly configured persistent service.
Build, deploy, and verify
A successful build alone does not prove the backend starts or the application works. A Git polling warning can coexist with a healthy older release.
- Create an App, connect the repository and branch, and select its manifest path.
- Configure build, frontend, and backend environment values. Keep secrets out of frontend bundles.
- Run the deployment. Webhost builds the frontend, builds and publishes the backend image, provisions shared PostgreSQL, and runs the configured migration.
- Inspect build logs and both runtime components. Verify the homepage, backend health route, real API requests, and database behavior through the public hostname.