Getting started
Welcome to our docs! Learn how to get started with the CommonGrants protocol.
Looking to jump right in? Skip to the quickstart tutorial to define a CommonGrants API using TypeSpec and explore the core routes and models defined by the protocol.
Find your way around
Section titled “Find your way around”Not looking for a quickstart guide? Here are some other resources to help you get started:
Quickstart
Section titled “Quickstart”The following tutorial will walk you through:
- Creating a new CommonGrants API specification using TypeSpec
- Compiling your project to OpenAPI and previewing it with Swagger
- Extending the base CommonGrants spec to include a custom field
- Viewing this new field in the OpenAPI docs
First steps
Section titled “First steps”First, we’ll show you how to set up and preview the default CommonGrants API specification using the CLI and quickstart template.
-
Install the CLI globally
Terminal window npm install @common-grants/cli -g -
Create a new directory for your project
Terminal window mkdir common-grants-quickstartcd common-grants-quickstart -
Initialize your project with the quickstart template.
Note: The TypeSpec compiler will warn you about using an untrusted template. This is expected and the template is safe to use.
Terminal window cg init --template quickstartFollow the prompts and accept the default options.
Terminal window ✔ Continue Yes✔ Enter a project name: common-grants-quickstart✔ Installing dependenciessuccess: Project initialized! -
Compile and preview your API specification at
http://localhost:3000Terminal window cg compile main.tspcg preview tsp-output/@typespec/openapi3/openapi.Quickstart.yaml
Deep dive
Section titled “Deep dive”Next, we’ll take a step back and walk you through what happened behind the scenes when you ran the CLI commands listed above.
If you want to jump straight into customizing the API spec, feel free to skip ahead to the Customization section.
Explore the files created by cg init
Section titled “Explore the files created by cg init”When you run cg init it sets up a new CommonGrants project in the common-grants-quickstart directory with the following files:
- main.tsp # Defines the API service
- routes.tsp # Defines the API routes
- tspconfig.yaml # Configures TypeSpec emitters (e.g. OpenAPI)
- package.json # Manages project dependencies
- .gitignore # Ignores files from the project
- README.md # The project README
We’ll focus on exploring the following files in particular:
Understanding routes.tsp
Section titled “Understanding routes.tsp”The routes.tsp file is the TypeSpec file that defines the API routes.
import "@common-grants/core";
using TypeSpec.Http;
@tag("Opportunities")@route("/common-grants/opportunities")namespace Quickstart.Routes { alias OpportunitiesRouter = CommonGrants.Routes.Opportunities;
op list is OpportunitiesRouter.list; op read is OpportunitiesRouter.read; op search is OpportunitiesRouter.search;}Since there’s a lot happening here, let’s break it down section by section.
-
Import the CommonGrants TypeSpec library.
import "@common-grants/core"; -
Expose the
TypeSpec.Httpnamespace.using TypeSpec.Http;This makes the
@routeand@tagkeywords available in the current namespace without requiring theTypeSpec.Httpprefix. -
Define a namespace for the
OpportunitiesRouter.@tag("Opportunities")@route("/common-grants/opportunities")namespace Quickstart.Routes {alias OpportunitiesRouter = CommonGrants.Routes.Opportunities;// operations omitted for brevity}Think of the
OpportunitiesRouteras a controller in a traditional MVC framework that groups related routes together under theOpportunitiestag and exposes them at the/common-grants/opportunitiespath. -
Expose the default routes from the CommonGrants library.
@tag("Opportunities")@route("/common-grants/opportunities")namespace Quickstart.Routes {alias OpportunitiesRouter = Opportunities;op list is OpportunitiesRouter.list;op read is OpportunitiesRouter.read;op search is OpportunitiesRouter.search;}This exposes the following default routes from the CommonGrants library:
GET /common-grants/opportunitiesGET /common-grants/opportunities/{id}POST /common-grants/opportunities/search
Understanding main.tsp
Section titled “Understanding main.tsp”The main.tsp file is the TypeSpec file that defines the API service.
import "@typespec/http";import "@typespec/versioning";import "@common-grants/core";
import "./routes.tsp";
/** API description here */@service(#{ title: "Quickstart API" })@Versioning.useDependency(CommonGrants.Versions.v0_2)namespace Quickstart;Let’s break down the main.tsp file section by section.
-
Import the TypeSpec HTTP module and the
routes.tspfile.import "@typespec/http";import "./routes.tsp";Importing the
routes.tspincludes the routes from that file in the OpenAPI document generated by thecg compilecommand. -
Define the API service.
/** API description here */@service(#{ title: "Quickstart API" })@Versioning.useDependency(CommonGrants.Versions.v0_2)namespace Quickstart;This defines the API service with a title of “Quickstart API”. The
@servicekeyword is used to define the API service and is required for the OpenAPI emitter to work. Thetitleproperty is used to set the title of the API and the docstring is used to set the description of the API in the OpenAPI docs. -
Specify the version of the CommonGrants protocol to use.
/** API description here */@service(#{ title: "Quickstart API" })@Versioning.useDependency(CommonGrants.Versions.v0_2)namespace Quickstart;This specifies that the Quickstart API should use the models and routes defined in the v0.2.x version of the CommonGrants protocol.
Understanding tspconfig.yaml
Section titled “Understanding tspconfig.yaml”The tspconfig.yaml file is the TypeSpec configuration file that defines the emitters for the project.
emitters: - "@typespec/json-schema" - "@typespec/openapi3"This configures the TypeSpec compiler to emit the API definition as an OpenAPI document and a JSON Schema.
Explore the packages installed by cg init
Section titled “Explore the packages installed by cg init”When you run cg init, the following packages are installed (among others):
@common-grants/coreThe CommonGrants TypeSpec library, which includes a default set of models and routes that can be used to define your own CommonGrants API.@typespec/openapi3The OpenAPI emitter for TypeSpec, which emits the CommonGrants API definition as an OpenAPI document.@typespec/json-schemaThe JSON Schema emitter for TypeSpec, which emits the models in your CommonGrants API as JSON Schemas.
Explore the files created by cg compile
Section titled “Explore the files created by cg compile”This will create a tsp-output directory with the following files compiled from main.tsp:
Directory
tsp-output/Directory
@typespec/Directory
openapi3/Auto-generated by the OpenAPI emitteropenapi.CommonGrants.yamlThe base CommonGrants API specopenapi.Quickstart.yamlThe quickstart API spec
Directory
json-schema/Auto-generated by the JSON Schema emitterCustomEnumValue.yamlOpportunity.yaml- …
Understanding the cg preview command
Section titled “Understanding the cg preview command”The cg preview command starts a local server that serves the OpenAPI specification using Swagger UI. View your API specification at http://localhost:3000.
Customization
Section titled “Customization”Finally, we’ll show you how to extend the base CommonGrants API specification with a custom field.
Add a custom field to the Opportunity model
Section titled “Add a custom field to the Opportunity model”Create a new file called models.tsp with the following code:
import "@common-grants/core";
// Allows us to use models defined in the specification library// without prefixing each model with `CommonGrants`using CommonGrants.Models;using CommonGrants.Fields;
namespace Quickstart.Models;
model Agency extends CustomField { name: "Agency"; type: CustomFieldType.string; value: string; description: "The agency managing the funding opportunity.";}
// Create a custom Opportunity type using the templatemodel CustomOpportunity extends OpportunityBase { @example(#{ agency: #{ name: "Agency", type: CustomFieldType.string, value: "Department of Energy", description: "The agency managing the funding opportunity.", }, }) customFields: { agency: Agency; };}There’s a lot happening here, so let’s break it down section by section.
-
Import the CommonGrants TypeSpec library.
import "@common-grants/core"; -
Make the CommonGrants fields, models, etc. available in the current namespace.
using CommonGrants.Fields;using CommonGrants.Models;Without this, you would have to prefix each model with
CommonGrants.Modelsand each field withCommonGrants.Fields. For exampleCommonGrants.Fields.CustomField. -
Declare a namespace for the current file.
namespace Quickstart.Models; -
Define a custom field by extending the
CustomFieldmodel.model Agency extends CustomField {name: "Agency";type: CustomFieldType.string;value: string;description: "The agency managing the funding opportunity.";}The
Agencymodel defines literal values for the field’sname,type, anddescriptionmetadata properties, and requires thevalueproperty to be a string. -
Extend the
OpportunityBasemodel to include this custom field.model CustomOpportunity extends Models.OpportunityBase {// Example omitted for brevitycustomFields: {agency: Agency;};}It also provides an example of the updated
customFieldsproperty, which will be displayed in the OpenAPI docs.model CustomOpportunity extends Opportunity.OpportunityBase {@example(#{agency: #{name: "Agency",type: Fields.CustomFieldType.string,value: "Department of Energy",description: "The agency managing the funding opportunity."}})customFields: {agency: Agency;};}
Update the default routes
Section titled “Update the default routes”Update the routes.tsp file and make the following changes:
- Import the
models.tspfile to expose theCustomOpportunitymodel. - Update the routes to use the
CustomOpportunitymodel.
import "@common-grants/core";import "./models.tsp";
using TypeSpec.Http;
@tag("Opportunities")@route("/common-grants/opportunities")namespace Quickstart.Routes { alias OpportunitiesRouter = CommonGrants.Routes.Opportunities;
op list is OpportunitiesRouter.list; op read is OpportunitiesRouter.read; op search is OpportunitiesRouter.search; op list is OpportunitiesRouter.list<Models.CustomOpportunity>; op read is OpportunitiesRouter.read<Models.CustomOpportunity>; op search is OpportunitiesRouter.search<Models.CustomOpportunity>;}Let’s explain these changes section by section.
-
Import the
models.tspfile to expose theCustomOpportunitymodel.import "./models.tsp"; -
Update the default routes to use the
CustomOpportunitymodel.@tag("Opportunities")@route("/common-grants/opportunities")namespace Quickstart.Routes {alias OpportunitiesRouter = Opportunities;op list is OpportunitiesRouter.list<Models.CustomOpportunity>;op read is OpportunitiesRouter.read<Models.CustomOpportunity>;op search is OpportunitiesRouter.search<Models.CustomOpportunity>;}This updates
GET /opportunitiesandGET /opportunities/{id}to return ourCustomOpportunitymodel instead of the default model from the CommonGrants library.
The updated routes.tsp file should now look like this:
import "@common-grants/core";import "./models.tsp";
using TypeSpec.Http;
@tag("Opportunities")@route("/common-grants/opportunities")namespace Quickstart.Routes { alias OpportunitiesRouter = CommonGrants.Routes.Opportunities;
op list is OpportunitiesRouter.list<Models.CustomOpportunity>; op read is OpportunitiesRouter.read<Models.CustomOpportunity>; op search is OpportunitiesRouter.search<Models.CustomOpportunity>;}View your changes
Section titled “View your changes”cg compile main.tspcg preview tsp-output/@typespec/openapi3/openapi.Quickstart.yamlThis should start a local server that serves the OpenAPI specification using Swagger UI. View your API specification at http://localhost:3000.
Specifically look for the agency field in the customFields property of the Opportunity model at http://localhost:3000/#/Opportunities/Routes_read. It should look something like this:

Next steps
Section titled “Next steps”Learn more about the CommonGrants protocol:
Learn more about TypeSpec: