Create a Node.js Service
This guide walks you through creating a production-ready Node.js microservice from zero using the Golden Path template โ from an empty repository to a fully cataloged, CI-enabled service in under 5 minutes.
Prerequisitesโ
- ForgePortal is running (local or deployed) โ see Quick Start
- A GitHub (or GitLab) token is configured with
reposcope โ see SCM Providers - Your ForgePortal role is
developeror higher โ see Role Guide
Step 1 โ Open the Templateโ
- Click Templates in the top navigation bar.
- Find the Node.js Service card (it has tags:
nodejs,typescript). - Click "Create โ".
You are taken to the template form.
Step 2 โ Fill the Wizardโ
Fill in each field:
| Field | Example | Notes |
|---|---|---|
| Service name | payment-service | Lowercase, hyphen-separated. Becomes the repo name and catalog entity name. |
| Description | Handles payments and invoicing | Shown in the catalog. |
| Owner | team-platform | Used in entity.yaml. |
| Lifecycle | experimental | Promote to production when ready. |
| GitHub Org | my-github-org | The org (or user) where the repo will be created. |
| Visibility | private | Use public for open-source projects. |
All fields with a * are required. Optional fields show a lighter label. You can leave them blank and update the entity.yaml later.
Click "Create Service" to start the run.
Step 3 โ Watch the Runโ
You are redirected to the run progress page (/templates/runs/:id). You see each step execute in order:
| Step | What happens |
|---|---|
scm.createRepo | New repo payment-service is created in your org |
scm.pushFiles | Scaffolded files are committed to a feat/scaffold branch |
scm.openPullRequest | PR opened: "chore: initial scaffold" |
catalog.registerEntity | entity.yaml committed ยท entity visible in the catalog |
Each step shows a status indicator (โณ queued โ ๐ running โ โ success). If a step fails, you see the error message and a hint.
When the run completes, you see links to:
- Repository URL โ the new repo on GitHub/GitLab
- Pull Request URL โ the scaffold PR ready for review
The SCM API calls are synchronous. If your token doesn't have repo write scope, step 1 fails with a 403 error. See SCM Providers to fix the token.
Step 4 โ Review and Merge the PRโ
Open the PR URL from the run outputs. You see:
feat/scaffold โ main
Files added:
package.json
tsconfig.json
src/index.ts
Dockerfile
.github/workflows/ci.yml
README.md
entity.yaml
Review the files. When satisfied, merge the PR.
entity.yaml firstThe entity.yaml file is the most important โ it defines how the service appears in the catalog. Check the owner, lifecycle, and description match your expectations.
Step 5 โ See the Entity in the Catalogโ
- Click Catalog in the top navigation.
- Search for
payment-serviceor filter by kindservice. - Click the entity to open its detail page.
You see:
- Overview tab โ description, owner, lifecycle, tags, links
- Scorecards tab โ initial evaluation (Bronze should pass immediately with owner set)
- Docs tab โ content of the
README.mdrendered as documentation
Step 6 โ Check the Scorecardโ
On the entity detail page, click Scorecards.
The default scorecard evaluates:
| Rule | Level | Expected |
|---|---|---|
| Owner is set | Bronze | โ pass (you set it in the form) |
| README exists | Bronze | โ pass (generated by template) |
| CI workflow exists | Silver | โ pass (generated by template) |
| Dockerfile exists | Silver | โ pass (generated by template) |
| Security scanning configured | Gold | โณ pending โ needs Snyk/SonarCloud |
Your service starts at Bronze / Silver. To reach Gold, configure Snyk or SonarCloud and add their annotations to entity.yaml.
What Was Generatedโ
src/index.tsโ
import Fastify from 'fastify';
const app = Fastify({ logger: true });
app.get('/health', async () => ({ status: 'ok' }));
app.listen({ port: 3000, host: '0.0.0.0' }, (err) => {
if (err) { app.log.error(err); process.exit(1); }
});
Dockerfileโ
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:22-alpine AS runner
WORKDIR /app
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/index.js"]
entity.yamlโ
apiVersion: forgeportal/v1
kind: service
metadata:
name: payment-service
namespace: default
description: Handles payments and invoicing
tags:
- nodejs
- typescript
spec:
owner: team-platform
lifecycle: experimental
Next Stepsโ
Now that your service is in the catalog, you can:
- Add a database โ Run the Create Database template and reference it in your
entity.yamlwithspec.dependsOn: ["resource:orders-db"] - Enable the Kubernetes plugin โ Add the annotation
forgeportal.dev/kubernetes-label-selector: app=payment-serviceto yourentity.yaml - Enable GitHub Insights โ Automatic โ the plugin reads commits/PRs from your repo via the GitHub token
- Push to Gold โ Add Snyk (
forgeportal.dev/snyk-org: my-org) and re-evaluate the scorecard
For a full end-to-end walkthrough of all three golden paths in sequence, see Golden Paths Overview.