> ## Documentation Index
> Fetch the complete documentation index at: https://docs.marina.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Anatomy of a Marina app

> What a Marina app is made of, which tech stacks work, and how requests reach your code.

A Marina app is one of two kinds:

* **Static**: files served to the browser. Anything that produces HTML, CSS,
  and JavaScript works.
* **Dynamic**: a request handler that runs on Marina, with access to platform
  services (database, storage, jobs, AI, connections).

One project can be both: static assets plus an entrypoint for API routes.

## Supported stacks

| You have | It works because |
| - | - |
| A plain `index.html` (with any assets) | Published as-is. |
| A framework project with a `build` script (Vite, React, Vue, Svelte, Astro, and similar) | Marina runs `npm run build` and publishes the output. `dist`, `build`, `out`, `public`, and `.output/public` are recognized when they contain `index.html`. |
| A JavaScript or TypeScript request handler | Declared as the `entrypoint` in `marina.json`; Marina installs npm dependencies, bundles it, and runs it. |

Not supported: apps that start their own server and listen on a port
(Express, Fastify, and similar), and languages other than JavaScript and
TypeScript for the handler. Deploy source, not build output: if a project
has a build step, Marina runs it, which keeps the app editable in Studio.
Builds run offline, so everything a build needs must be in the project or
its npm dependencies.

## Project layout

```text theme={null}
my-app/
├── marina.json              # manifest: name, entrypoint, services, jobs, connections
├── src/app.ts               # request handler (dynamic apps)
├── marina/migrations/       # SQL migrations, applied in order (if using the database)
├── index.html               # or a build script producing static output
└── package.json
```

## The request handler

A dynamic app exports a handler. Marina passes each request plus the services
the manifest declares:

```ts src/app.ts theme={null}
import { defineApp } from "@marina/runtime";

export default defineApp({
  async fetch(request, marina) {
    const url = new URL(request.url);
    if (url.pathname === "/api/expenses") {
      const result = await marina.db.query("select * from expenses limit 100");
      return Response.json(result.rows);
    }
    return new Response("Hello");
  },
});
```

The environment is Web-standard: `Request`, `Response`, `fetch`, `URL`,
`crypto`, and friends. TypeScript needs no build configuration; Marina
bundles the entrypoint for you. There is no port to listen on and no server
to manage: export the handler and Marina routes requests to it.

`marina` carries only the services the version declares in its manifest.
Calling an undeclared service fails with a clear error naming the
declaration to add.

## Who is making the request

Marina authenticates viewers before requests reach your app and identifies
them with headers such as `x-platform-user-id`. Your code can trust these for
per-user data without building sign-in. Callers without a browser can use
[app keys](/guides/app-keys) or [temporary links](/guides/temporary-links).

## From code to running app

`marina deploy` uploads the project, builds it, and publishes an immutable
version. Changes that expand what an app can touch (a new service, a new
connection, new migrations) go through an approval before the version goes
live. During development, [`marina dev`](/guides/local-development) runs the
same code locally.

<CardGroup cols={2}>
  <Card title="App configuration" icon="file-cog" href="/guides/app-configuration">
    The full `marina.json` reference.
  </Card>

  <Card title="Deployments and versions" icon="git-branch" href="/guides/deployments">
    Builds, approvals, versions, and rollback.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.