Skip to content
Content
Skill

/project-structure

Webiny project layout, webiny.config.tsx anatomy, and extension registration. Use this skill when the developer asks about folder structure, where custom code goes, how to register extensions, what webiny.config.tsx does, or how the project is organized. Also use when they need

BOOST
From plugin
webiny-js
8k76 skills3 MCP
Install
$ npx -y skills add webiny/webiny-js --skill project-structure --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/project-structure

Context preview

The summary Claude sees to decide when to auto-load this skill.

Webiny project layout, webiny.config.tsx anatomy, and extension registration. Use this skill when the developer asks about folder structure, where custom code goes, how to register extensions, what webiny.config.tsx does, or how the project is organized. Also use when they need

SKILL.md

project-structure.SKILL.md
name: webiny-project-structure
description: >
  Webiny project layout, webiny.config.tsx anatomy, and extension registration.
  Use this skill when the developer asks about folder structure, where custom code goes,
  how to register extensions, what webiny.config.tsx does, or how the project is organized.
  Also use when they need to understand the relationship between extensions/, webiny.config.tsx,
  and the different extension types (Api, Admin, Infra, CLI).

Webiny Project Structure

TL;DR

A Webiny project has a flat structure centered around `webiny.config.tsx` -- the single configuration file where all extensions are registered. Custom code lives in the `extensions/` folder. Extensions are registered as React components (`<Api.Extension>`, `<Admin.Extension>`, `<Infra.*>`, `<Cli.Command>`) and can be conditionally loaded per environment.

Project Layout

my-webiny-project/
├── extensions/          # All custom code -- API, Admin, Infra, CLI extensions
│   └── README.md
├── public/              # Static assets for the Admin app
│   ├── favicon.ico
│   ├── global.css
│   ├── index.html
│   └── robots.txt
├── package.json         # Single package.json for the whole project
├── tsconfig.json        # Single TypeScript config
├── webiny.config.tsx    # Main configuration -- all extensions registered here
├── webiny-env.d.ts      # TypeScript environment types
└── yarn.lock

Key points:

  • **Single `package.json`** -- no monorepo, no workspaces needed.
  • **Single `tsconfig.json`** -- straightforward TypeScript setup.
  • **`webiny.config.tsx`** -- the entry point for everything. All extensions, infrastructure options, and project settings are declared here.
  • **`extensions/`** -- where all your custom code lives. Organize with subfolders as needed (e.g., `extensions/contactSubmission/`, `extensions/AdminBranding/`).

The `webiny.config.tsx` File

This file exports a single React component called `Extensions`. It uses JSX to declaratively register all configuration:

// webiny.config.tsx
import React from "react";
import { Admin, Api, Cli, Infra, Project, Security } from "webiny/extensions";
import { Cognito } from "@webiny/cognito";

export const Extensions = () => {
  return (
    <>
      {/* Infrastructure configuration */}
      <Infra.Aws.DefaultRegion name={"us-east-1"} />
      <Infra.OpenSearch enabled={true} />
      <Infra.Aws.Tags tags={{ OWNER: "me", PROJECT: "my-project" }} />

      {/* Identity provider */}
      <Cognito />

      {/* API extensions (backend) */}
      <Api.Extension src={"/extensions/ProductCategoryModel.ts"} />
      <Api.Extension src={"/extensions/ProductModel.ts"} />
      <Api.Extension src={"/extensions/contactSubmission/ContactSubmissionHook.ts"} />

      {/* Security hooks */}
      <Api.Extension src={"/extensions/MyApiKey.ts"} />
      <Security.ApiKey.AfterUpdate src={"/extensions/MyApiKeyAfterUpdate.ts"} />

      {/* Admin extensions (frontend) */}
      <Admin.Extension src={"/extensions/AdminTheme/AdminTheme.tsx"} />
      <Admin.Extension src={"/extensions/AdminTitleLogo/AdminTitleLogo.tsx"} />
      <Admin.Extension src={"/extensions/contactSubmission/EmailEntryListColumn.tsx"} />

      {/* Infrastructure / Pulumi extensions */}
      <Infra.Core.Pulumi src={"/extensions/MyCorePulumiHandler.ts"} />

      {/* CLI extensions */}
      <Cli.Command src={"/extensions/MyCustomCommand.ts"} />

      {/* Project settings */}
      <Project.Telemetry enabled={false} />
    </>
  );
};

Extension Types

| JSX Element | What It Does | File Type | | ------------------------------------------- | ---------------------------------------------------------------------------------------- | --------- | | `<Api.Extension src="..." />` | Registers a backend extension (GraphQL schemas, content models, lifecycle hooks) | `.ts` | | `<Admin.Extension src="..." />` | Registers a frontend Admin UI extension (themes, branding, custom columns, custom forms) | `.tsx` | | `<Infra.Core.Pulumi src="..." />` | Registers a Pulumi infrastructure handler | `.ts` | | `<Cli.Command src="..." />` | Registers a custom CLI command | `.ts` | | `<Security.ApiKey.AfterUpdate src="..." />` | Registers a security lifecycle hook | `.ts` |

**YOU MUST include the full file path with the `.ts` or `.tsx` extension in every `src` prop.** For example, use `src={"/extensions/MyModel.ts"}`, NOT `src={"/extensions/MyModel"}`. Omitting the file extension will cause a build failure.

**YOU MUST use `export default` for the `createImplementation()` call** when the file is targeted directly by an Extension `src` prop. Using a named export (`export const Foo = SomeFactory.createImplementation(...)`) will cause a build failure. Named exports are only valid inside files registered via `createFeature`.

Infrastructure Components

Declarative components for configuring AWS infrastructure:

| Component | Purpose | | --------------------------------------------------------------------- | -------------------------------------- | | `<Infra.Aws.DefaultRegion name="us-east-1" />` | Set the AWS region | | `<Infra.Aws.Tags tags={{ KEY: "value" }} />` | Apply tags to all AWS resources | | `<Infra.OpenSearch enabled={true} />` | Enable/disable OpenSearch | | `<Infra.Vpc enabled={true} />` | Enable/disable VPC deployment | | `<Infra.PulumiResourceNamePrefix prefix="myproj-"

Read more
Ships withwebiny-js

Open-source content platform. Self-hosted on AWS serverless. Built as a TypeScript framework you extend with code, not a closed product you configure through a UI. Runs on Lambda, DynamoDB, S3, and CloudFront inside your own AWS account. Scales automatically.

Get the whole plugin
Stats
8,049
Stars
682
Forks
Active
Maintenance
TypeScript
Language
18h ago
Last commit
8y ago
Created
2d ago
Added

Repo: webiny/webiny-js

Other skills on webiny-js.