# Components

URL: /code/file-conventions/components · Id: `page:code/file-conventions/components`

> A Component in components/ declares typed props and renderings once, shared by every Site, App and Dashboard.

A [Component](/business/nouns/component) in `components/` declares its typed props and renderings once. Every [Site](/business/nouns/site), [App](/business/nouns/app) and [Dashboard](/business/nouns/dashboard) of the [Startup](/business/nouns/startup) uses it.

```text
components/
├── RenewalCountdown.mdx     props and renderings
├── RenewalCountdown.tsx     its web rendering
└── RenewalCountdown.css     its scoped CSS
```

## Reference
| [File](/business/nouns/file) | Holds |
| --- | --- |
| `[Name].mdx` | Frontmatter `props` and `renderers`; the body documents it |
| `[Name].tsx` | The web rendering, composed from `startup-builder/ui` |
| `[Name].css` | One scoped layer of CSS |

A prop's `type` is a scalar or a [Noun](/business/nouns/noun) name. `renderers` lists `web`, `native` and `markdown`; each Component renders for people, native clients and agents.

## Examples
### Minimal
```mdx title="components/RenewalCountdown.mdx"
---
props:
  lease: { type: Lease, required: true }
renderers: [web, markdown]
---
```

### Leaseline
Leaseline declares a `Lease` Noun.

```tsx title="components/RenewalCountdown.tsx"
import { StateBadge, Timeline } from 'startup-builder/ui'

export default function RenewalCountdown({ lease }: { lease: Lease }) {
  const days = Math.ceil((Date.parse(lease.endsOn) - Date.now()) / 86_400_000)
  return (
    <section>
      <h3>{lease.unit}: {days} days to renewal</h3>
      <StateBadge thing={lease.$id} />
      <Timeline thing={lease.$id} />
    </section>
  )
}
```

## What it builds
The [SiteBuilder](/code/builders/site) compiles the files.

- a `Component` whose props become typed for every [Page](/business/nouns/page), view and Dashboard
- its Markdown rendering, so agents read what people see

## Good to know
- The built-in catalog is [UI components](/code/ui/components).