A scaffolded Teasim project is an ordinary Astro project. Everything you will edit is a real file in your repository; all three packages stay dependencies and are never copied in.
npx astra create my-docsyarn dlx astra create my-docspnpm dlx astra create my-docsbunx astra create my-docsWhat lands in your repository
my-docs
├── astro.config.mjs
├── index.css
├── package.json
├── tsconfig.json
└── src
├── content.config.ts
├── content
│ └── docs
│ ├── index.mdx
│ └── brewing.md
├── helpers
│ └── docs.ts
└── pages
└── [...slug].astro| Path | What it is |
|---|---|
index.css |
The TeaCSS entry — presets, @source globs, @teacss;. This file is the configuration; there is no teacss.config.* |
astro.config.mjs |
teacss() and astra(), plus markdown.shikiConfig, prefetch, and vite.resolve.noExternal |
src/content.config.ts |
The docs collection, from astra’s docsCollection() |
src/content/docs/ |
Your pages. The tree here is the site |
src/helpers/docs.ts |
The glue: collection entries in, navigation data out |
src/pages/[...slug].astro |
One route for every page, and the landing page too — there is no separate index.astro |
Ten files, two of them seed content. One .md and one .mdx on purpose: the
pair proves both parse paths the moment the dev server starts.
The tree is the structure
The directory layout under src/content/docs/ is the URL structure and the
sidebar. The path is the structure — guides/installing nests under
guides whether or not guides is a page in its own right.
src/content/docs
├── index.mdx → /
├── project-structure.mdx → /project-structure
├── components
│ └── accordion.mdx → /components/accordion
└── references
└── create-navigation.mdxA directory with no entry of its own becomes a heading in the sidebar: its
slug and href are null, it is not navigable, and it takes its label from
the path segment, title-cased. That is why Components and References
appear in the rail on the left without being pages.
Move a file and its route and its sidebar entry move with it. Frontmatter
handles the fine grain — sidebar.order, sidebar.badge, draft — but the
shape of the site comes from the filesystem. There is no second navigation
config to keep in sync, so the site cannot drift from its own contents.
What is yours and what is not
The three packages divide by what they produce:
| Package | Ships | Knows about |
|---|---|---|
@teasim/astro |
elements — Button, Dialog, Prose | behaviour and accessibility |
@teasim/aster |
blocks — SiteShell, SiteNav, SitePricing | arrangement |
@teasim/astra |
data helpers, the Astro integration, the CLI | your content |
The direction is one-way: aster composes astro, your page composes both, and
astra imports neither. astra computes, astro draws, aster arranges, the page
glues — which is why PackageManagers takes commands already translated
rather than importing astra’s translatePackageCommand itself.
Nothing is vendored. There is no upstream theme to override and no copy in your
repository to diff against, so upgrading the chrome is npm update.
What the integration adds
astra() in your Astro config injects three routes you never write:
| Route | Contents |
|---|---|
/llms.txt |
The sidebar flattened to links and descriptions |
/llms-full.txt |
Every page body as markdown, slug-ordered |
/[...slug].md |
One page body as markdown |
They are wired together on purpose: an agent reads /llms.txt, follows a link,
and gets markdown rather than HTML it has to strip. Try
/llms.txt or the markdown twin of this page,
/project-structure.md.
To take one over, create the file — src/pages/llms.txt.ts and that route is
yours, no option required.
What is not in the tree
.astro/ is generated: content-collection types and the resolved config. It is
gitignored, and nothing in it is yours to edit.
There is no config file of astra’s own. Everything it needs is an option on the
astra() call, and nothing else in the project reads one — including site,
which stays on Astro’s defineConfig because the sitemap, the canonical URL,
and Astro.site all read it from there.