# Quick Start: Create and Store Data Locally

This procedure creates a namespace, a resource template, a resource, and a process template in a local SQLite database. Builders validate nested models and persist an aggregate when their context manager exits successfully.


# Create a client and namespace

``` python
from recap.client import RecapClient

with RecapClient.from_sqlite("experiment.db") as client:
    client.create_namespace("beamline")
    client.create_namespace("beamline/amx", metadata={"beamline": "amx"})
    namespace = client.namespace("beamline/amx")
```

[from_sqlite()](../../reference/RecapClient.md#recap.RecapClient.from_sqlite) creates or upgrades the database. A namespace path scopes queries and writes; it also allows the same template or resource name to exist in separate namespaces.


# Define a resource template

``` python
with namespace.build_resource_template(
    name="Sample Plate",
    type_names=["container", "plate"],
) as template:
    template.add_properties({
        "dimensions": [
            {"name": "rows", "type": "int", "default": 8},
            {"name": "columns", "type": "int", "default": 12},
        ]
    })
```

Resource templates define the shape of resources, including property groups, typed attributes, defaults, and child templates.


# Create a resource

``` python
with namespace.build_resource(
    name="Sample Plate 001",
    template_name="Sample Plate",
) as builder:
    pass
resource = builder.resource
```

Resources receive identity, namespace ownership, metadata, and lifecycle state. The returned schema is a local model; subsequent database changes still go through a client or builder.


# Query the result

``` python
plate = (
    namespace.query_maker()
    .resources()
    .filter(name="Sample Plate 001")
    .first()
)

assert plate is not None
```

Continue with [Query resources](../../docs/how-to/query-resources.md) for filtering, ordering, pagination, and relationship loading. To run the same workflow through a server, [set up a RECAP server](../../docs/how-to/setup-recap-server.md) and replace [RecapClient.from_sqlite()](../../reference/RecapClient.md#recap.RecapClient.from_sqlite) with [RecapClient.from_url()](../../reference/RecapClient.md#recap.RecapClient.from_url).
