EN FR

Chapter 04Get started

Anatomy of a project

Every file, its role, and above all: which ones you will touch daily, which ones never. Plus the full list of commands.

5 min read8 sectionsChapter 4 / 22

A site project

This is what npm create inline@latest produces, and what you version in the client's repository.

site tree text
my-site/
├── astro.config.mjs           ★ integration, languages, static output
├── package.json               ★ site scripts
├── wrangler.toml                function configuration for the host
├── tsconfig.json
├── .env.example                 variable template — the only versioned one
├── .dev.vars                    local variables — ignored by Git
├── .gitignore
│
├── functions/
│   └── api/
│       ├── auth.ts              ┐
│       ├── content.ts           │ four 5-line adapters,
│       ├── save.ts              │ never a rule
│       └── upload.ts            ┘
│
├── scripts/
│   ├── check-html.mjs           content present in raw HTML
│   ├── check-locales.mjs        key parity across languages
│   ├── check-logs.mjs           no secret in a console.*
│   ├── check-secrets.mjs        no secret in dist/
│   ├── make-key.mjs             a key and its hash — rotation
│   └── mock-git-api.mjs         fake local repository
│
├── src/
│   ├── content/
│   │   ├── config.ts            collection declaration (schema from the package)
│   │   ├── site.json          ★ navigation, contact details, footer
│   │   ├── site.ts              site.json validation at build time
│   │   └── pages/
│   │       ├── fr/home.json   ★ THE content — one page, one language, one file
│   │       └── en/home.json   ★
│   │
│   ├── components/            ★ your components — static by default
│   │   └── Testimonial.astro
│   ├── layouts/
│   │   └── Base.astro         ★ metadata, navigation, footer
│   ├── lib/
│   │   └── locales.ts         ★ the languages of THIS site
│   ├── media/                 ★ the images — in src/, not in public/
│   │   └── library.ts           created by the integration, leave as is
│   ├── pages/
│   │   └── [lang]/[...slug].astro  ★ the page template
│   └── styles/
│       └── theme.css          ★ THE theme: palette, scale, rhythm
│
└── .github/workflows/ci.yml     automated checks

★ = files you edit for a given site.

Every day

Content and theme

src/content/pages/**, src/styles/theme.css, src/components/, the page template.

Once per site

Configuration

astro.config.mjs, src/lib/locales.ts, src/content/site.json, the environment variables.

Never

Adapters and checks

functions/api/*.ts and scripts/check-*.mjs: they ship correct. Adding a rule there is a symptom, not a solution.

The shared package

inline-core is not in the site repository: it is a dependency installed in node_modules. Its structure tells you where to read when hunting for a behaviour.

packages/inline-core text
inline-core/
├── astro/index.ts             the integration: /admin, /aide, overlay, bootstrap
├── components/
│   ├── Editable.astro         a text or richtext field
│   ├── Media.astro            an image or a video
│   └── Collection.astro       a list + its item template
├── pages/
│   ├── admin.astro            the key entry page
│   └── aide.astro             the client help page, ready to use
├── styles/tokens.css          one class per schema value
└── src/
    ├── schema.ts              THE content model (Zod) — build AND server
    ├── style-tokens.ts        the allowed variants, single source
    ├── safe-href.ts           what a safe link is, on both sides
    ├── video.ts               reading a YouTube / Vimeo address
    ├── translate.ts           translation fallback (not the language list)
    ├── editor/                the overlay — TypeScript, no framework
    │   ├── index.ts           the loop: a path, a pointer, a mutation
    │   ├── bar.ts             floating bar and banners
    │   ├── toolbar.ts         variants and richtext toolbars
    │   ├── media.ts           image / video panel
    │   ├── collection.ts      add, duplicate, move, delete
    │   ├── draft.ts           local draft
    │   ├── sanitize.ts        browser-side sanitising
    │   ├── heic.ts            iPhone photo decoding, on demand
    │   └── api.ts             the calls to the four routes
    └── server/
        ├── auth.ts            verifyAuth / createSession — sole judge of identity
        ├── guard.ts           rate, caps, allowed paths
        ├── rate-limit.ts      call counting, interchangeable storage
        ├── git-provider.ts    the Git provider interface
        ├── github.ts          GitHub implementation (version = blob SHA)
        ├── gitlab.ts          signature + notes — not implemented
        ├── image.ts           format recognition from the bytes
        ├── sanitize.ts        server-side sanitising (no DOM)
        └── routes/            the four routes, as configurable factories

What is imported, and under which name

ImportWhat it isWhere it is used
inline-core/astroThe integrationastro.config.mjs
inline-core/schemaZod schemas and typessrc/content/config.ts, components
inline-core/style-tokensStyle enums and styleClasses()Components, tooling
inline-core/components/Editable.astroText / richtext fieldPages
inline-core/components/Media.astroImage or videoPages
inline-core/components/Collection.astroList + item templatePages
inline-core/styles/tokens.cssToken classesThe layout
inline-core/serverThe four route factoriesfunctions/api/*.ts
inline-core/translatemergeWithDefault, localePathsrc/lib/locales.ts
inline-core/videoparseVideoUrl, embedUrlComponents, tooling

Commands

In a site

site created by npm create inline bash
npm run dev              # Astro server alone — layout, without editing
npm run build            # production build (fails if content is invalid)
npm run serve:functions  # site + functions: this is where you edit
npm run mock:git         # fake local Git repository
npm run make:key         # a key and its hash — rotation
npm run check            # raw HTML + language parity + logs + secrets

In the reference repository

inline repository bash
npm run dev              # Astro server alone
npm run build            # production build
npm run serve:functions  # site + functions on http://127.0.0.1:8788
npm run check            # the four checks
npm test                 # the whole test suite

npm run create:site      # prepares a site's credentials (key, hash, variables)
npm run make:key         # a key and its hash — rotation
npm run bootstrap        # extracts content from an annotated HTML page
npm run mock:git         # fake local Git repository

npm run test:scaffold    # creates a site from scratch, installs, builds, checks it
npm run test:pack        # same, from the archives a publication would produce
npm run pack:core        # builds the inline-core archive
npm run release:core     # publishes inline-core to the registry
The two commands that matter before a commit

npm test and npm run check — exactly the ones CI runs, and they block the branch. A check that does not block gets bypassed, then disabled, then removed.

Where does a change belong?

The question comes up with every evolution, and one wrong answer is enough to make ten sites diverge. The criterion is simple: would this be true for every client?

You want to…Where
change a colour, a heading size, a fontthe site's src/styles/theme.css
add a page, a block, a sectionsrc/content/pages/… + the page template
add a languageastro.config.mjs, src/lib/locales.ts, scripts/check-locales.mjs
add a field type (a table, say)inline-core/src/schema.tsmajor version
change a size cap or a rate budgetinline-core/src/server/guard.ts
fix a message shown to the clientinline-core/src/editor/*
support a new Git providerinline-core/src/server/ + GIT_PROVIDER
add an identity checkinline-core/src/server/auth.ts, and nowhere else
The symptom to recognise

If you are about to write a rule in functions/api/*.ts, stop. Those files hold three lines of wiring. A rule appearing there is a rule you will have to find again in every client repository the day it changes.

What the site must give the package

Three things, and only three:

  1. its configuration — the languages, passed to the integration and the routes;
  2. its contentsrc/content/pages/{language}/{page}.json;
  3. its appearance — the CSS variables tokens.css expects, its components, its layout.

If that list grows, it is a sign a package decision has leaked into the sites.