Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
encoredev avatar

Encore Getting Started

  • 470 installs
  • 26 repo stars
  • Updated May 15, 2026
  • encoredev/skills

encore-getting-started is an agent skill that bootstraps brand-new Encore.ts projects by installing the Encore CLI, running encore app create, defining the first typed API endpoint, and starting encore run for local deve

About

encore-getting-started is an Encore.dev agent skill strictly for first-time Encore.ts setup—not architecture or advanced feature questions. It walks through brew install encoredev/tap/encore on macOS, encore app create my-app with the ts/hello-world example, and defining a hello endpoint with api() from encore.dev/api. The minimal project layout includes encore.app, encore.service.ts, api.ts, and optional SQLDatabase migrations under ./migrations. Running encore run serves APIs at http://localhost:4000 and opens the local dashboard at http://localhost:9400 for traces, logs, and database queries. Developers reach for encore-getting-started only when they have no Encore project yet and need CLI install, hello-world scaffolding, or their first encore run.

  • Encore project initialization
  • Local development workflow
  • First Go service scaffolding
  • API backend bootstrap
  • Framework conventions onboarding

Encore Getting Started by the numbers

  • 470 all-time installs (skills.sh)
  • Ranked #24 of 98 Go skills by installs in the Skillselion catalog
  • Data as of Jul 24, 2026 (Skillselion catalog sync)
npx skills add https://github.com/encoredev/skills --skill encore-getting-started

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs470
repo stars26
Last updatedMay 15, 2026
Repositoryencoredev/skills

How do you bootstrap a new Encore.ts backend project?

Bootstrap new Encore Go backend projects with correct project layout, local dev workflow, and first service setup for API or SaaS backends.

Who is it for?

Backend developers starting their first Encore.ts service who need CLI install, project scaffolding, and a working hello-world API endpoint.

Skip if: Developers with an existing Encore project asking about pub/sub, auth, or service architecture should use encore-api, encore-auth, or encore-service skills instead.

When should I use this skill?

User has no Encore project yet and asks to install the Encore CLI, run encore app create, or start their first encore run hello-world app.

What you get

Encore CLI installation, encore.app project scaffold, first typed GET /hello endpoint, and running local dev server with dashboard.

  • Encore.ts project scaffold
  • hello-world API endpoint
  • running local dev server

By the numbers

  • Local API server runs at http://localhost:4000
  • Encore dev dashboard available at http://localhost:9400
  • Documents 5 common CLI commands including encore test and encore gen client

Files

SKILL.mdMarkdownGitHub ↗

Encore API Endpoints

Instructions

When creating API endpoints with Encore.ts, follow these patterns:

1. Import the API module

import { api } from "encore.dev/api";

2. Define typed request/response interfaces

Always define explicit TypeScript interfaces for request and response types:

interface CreateUserRequest {
  email: string;
  name: string;
}

interface CreateUserResponse {
  id: string;
  email: string;
  name: string;
}

3. Create the endpoint

export const createUser = api(
  { method: "POST", path: "/users", expose: true },
  async (req: CreateUserRequest): Promise<CreateUserResponse> => {
    // Implementation
  }
);

API Options

OptionTypeDescription
methodstringHTTP method: GET, POST, PUT, PATCH, DELETE
pathstringURL path, supports :param and *wildcard
exposebooleanIf true, accessible from outside (default: false)
authbooleanIf true, requires authentication
sensitivebooleanIf true, redacts request/response payloads from traces

Request/Response Patterns

Encore supports four endpoint configurations:

// Both request and response
export const createUser = api(
  { method: "POST", path: "/users", expose: true },
  async (req: CreateRequest): Promise<CreateResponse> => { ... }
);

// Response only (no request body)
export const listUsers = api(
  { method: "GET", path: "/users", expose: true },
  async (): Promise<ListResponse> => { ... }
);

// Request only (no response body)
export const deleteUser = api(
  { method: "DELETE", path: "/users/:id", expose: true },
  async (req: DeleteRequest): Promise<void> => { ... }
);

// Neither request nor response
export const ping = api(
  { method: "GET", path: "/ping", expose: true },
  async (): Promise<void> => { ... }
);

Custom HTTP Status Codes

Include an HttpStatus field in your response to return custom status codes:

import { api, HttpStatus } from "encore.dev/api";

interface CreateResponse {
  id: string;
  status: HttpStatus;
}

export const create = api(
  { method: "POST", path: "/items", expose: true },
  async (req: CreateRequest): Promise<CreateResponse> => {
    const item = await createItem(req);
    return { id: item.id, status: HttpStatus.Created };  // Returns 201
  }
);

Parameter Types

Path Parameters

// Path: "/users/:id"
interface GetUserRequest {
  id: string;  // Automatically mapped from :id
}

Query Parameters

import { Query } from "encore.dev/api";

interface ListUsersRequest {
  limit?: Query<number>;
  offset?: Query<number>;
}

Headers

import { Header } from "encore.dev/api";

interface WebhookRequest {
  signature: Header<"X-Webhook-Signature">;
  payload: string;
}

Cookies

import { Cookie } from "encore.dev/api";

interface SessionRequest {
  session?: Cookie<"session">;
  settings?: Cookie<"user-settings">;
}

Request Validation

Encore validates requests at runtime using TypeScript types. Add constraints for stricter validation:

import { api } from "encore.dev/api";
import { Min, Max, MinLen, MaxLen, IsEmail, IsURL } from "encore.dev/validate";

interface CreateUserRequest {
  email: string & IsEmail;                    // Must be valid email
  username: string & MinLen<3> & MaxLen<20>;  // 3-20 characters
  age: number & Min<13> & Max<120>;           // Between 13 and 120
  website?: string & IsURL;                   // Optional, must be URL if provided
}

Combining Validation Rules

Use & for AND logic (must pass all rules) and | for OR logic (must pass at least one):

import { IsEmail, IsURL, MinLen, MaxLen } from "encore.dev/validate";

interface ContactRequest {
  // Must be valid email OR valid URL
  contact: string & (IsEmail | IsURL);
  // Must be 5-100 chars AND be a valid URL
  website: string & MinLen<5> & MaxLen<100> & IsURL;
}

Available Validators

ValidatorApplies ToExample
Min<N>numberage: number & Min<18>
Max<N>numbercount: number & Max<100>
MinLen<N>string, arrayname: string & MinLen<1>
MaxLen<N>string, arraytags: string[] & MaxLen<10>
IsEmailstringemail: string & IsEmail
IsURLstringlink: string & IsURL
StartsWith<S>stringid: string & StartsWith<"usr_">
EndsWith<S>stringfile: string & EndsWith<".json">
MatchesRegexp<R>stringcode: string & MatchesRegexp<"^[A-Z]{3}$">

Validation Error Response

Invalid requests return 400 with details:

{
  "code": "invalid_argument",
  "message": "validation failed",
  "details": { "field": "email", "error": "must be a valid email" }
}

Error Handling

Use APIError for proper HTTP error responses:

import { APIError, ErrCode } from "encore.dev/api";

// Throw with error code
throw new APIError(ErrCode.NotFound, "user not found");

// Or use shorthand
throw APIError.notFound("user not found");
throw APIError.invalidArgument("email is required");
throw APIError.unauthenticated("invalid token");

Common Error Codes

CodeHTTP StatusUsage
NotFound404Resource doesn't exist
InvalidArgument400Bad input
Unauthenticated401Missing/invalid auth
PermissionDenied403Not allowed
AlreadyExists409Duplicate resource

Static Assets

Serve static files (HTML, CSS, JS, images) with api.static:

import { api } from "encore.dev/api";

// Serve files from ./assets under /static/*
export const assets = api.static(
  { expose: true, path: "/static/*path", dir: "./assets" }
);

// Serve at root (use !path for fallback routing)
export const frontend = api.static(
  { expose: true, path: "/!path", dir: "./dist" }
);

// Custom 404 page
export const app = api.static(
  { expose: true, path: "/!path", dir: "./public", notFound: "./404.html" }
);

Path Syntax

  • *path - Standard wildcard: matches all paths under the prefix (e.g., /static/*path)
  • !path - Fallback routing: serves static files at domain root without conflicting with other API endpoints. Use this for SPAs where unmatched routes should serve index.html

Guidelines

  • Always use import not require
  • Define explicit interfaces for type safety
  • Use expose: true only for public endpoints
  • Throw APIError instead of returning error objects
  • For inbound webhooks (Stripe, GitHub, etc.) use api.raw — see the encore-webhook skill
  • Path parameters are automatically extracted from the path pattern
  • Use validation constraints (Min, MaxLen, etc.) for user input

Related skills

How it compares

Use encore-getting-started only for zero-to-first-run Encore.ts setup; switch to encore-api or encore-database for feature work on existing projects.

FAQ

What does encore-getting-started cover?

encore-getting-started covers Encore CLI installation, encore app create, minimal Encore.ts project structure, defining a typed hello API with api() from encore.dev/api, and running encore run. It explicitly skips architecture and feature questions for existing projects.

What ports does a new Encore.ts app use locally?

encore-getting-started documents that encore run exposes APIs at http://localhost:4000 and the local development dashboard at http://localhost:9400, showing services, request logs, database queries, and traces.

Gobackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.