Quickstart
By the end of this page you have a running Raytha site, one published content item that you can open in a browser, and the same item returned by the REST API.
1. Start Raytha
Pick one. Both end at the same setup screen.
Deploy on Railway (recommended)
Railway is the fastest path: one click, with PostgreSQL included.
- Open the Raytha template on Railway and deploy it.
- When the deployment is healthy, open the public URL Railway assigns to the Raytha service.
Read Deploy with Railway before you put real content in: there are three things to check after the first deploy.
Run it with Docker
The image is published on Docker Hub as raythahq/raytha. You need Docker with the Compose plugin and nothing else: no clone, no .NET SDK. Save this as docker-compose.yml in an empty directory:
services:
app:
image: raythahq/raytha:2.0.0
ports:
- "5001:8080"
environment:
ASPNETCORE_ENVIRONMENT: Development
ConnectionStrings__DefaultConnection: Host=db;Port=5432;Username=postgres;Password=changeme;Database=raytha
APPLY_PENDING_MIGRATIONS: "true"
volumes:
- raytha_user_uploads:/app/user-uploads
depends_on:
db:
condition: service_healthy
db:
image: postgres:17
environment:
POSTGRES_PASSWORD: changeme
POSTGRES_DB: raytha
volumes:
- raytha_pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
raytha_pg_data:
raytha_user_uploads:
docker compose up
Docker pulls the image, which takes under a minute. When the log shows Application started, open http://localhost:5001. Migrations are applied automatically on first run. Use the latest tag if you always want the newest release, or pin a version as above.
Note
ASPNETCORE_ENVIRONMENT=Developmentis set so that plain HTTP works on localhost. Outside Development the sign-in cookie is markedSecureand you must serve the site over HTTPS. See Deploy with Docker for a production setup.
2. Create the first administrator
Until setup is complete, every public page redirects to /raytha/setup.
- Fill in First name, Last name, Email and Password. The password needs at least 8 characters.
- Check Website URL. The form prefills the address in your browser. Raytha builds links in emails and absolute media URLs from this value, so it must be the public address of the site (for example
https://www.example.com). - Select Create administrator. You are signed in and land on the dashboard at
/raytha.
Setup also creates a posts content type with a few sample posts, a home page, an About page, a navigation menu, the default theme, and the built-in roles (Super Admin, Admin, Editor).
3. Create a content type
- Open Content types in the sidebar and select New content type.
- Enter Singular label
Productand Plural labelProducts. The Developer name fills in asproducts. It becomes the content type's name in API URLs and in Liquid. - Leave the route template at its default,
{ContentTypeDeveloperName}/{PrimaryField}. It gives each item an address made from the content type and the item's title, such asproducts/Desk-lamp. The other tokens are{Id},{CurrentYear}and{CurrentMonth}. - Save. A new content type starts with a
titlefield (the primary field), acontentrich text field, and an "All products" view that is published at/products.
To add more fields, open the content type's fields page and add them with a label, a developer name and a field type.
4. Publish an item
- Open Products in the sidebar and select New Product.
- Fill in the title and content. Leave Template as it is.
- Select Publish. (Save draft keeps it private.)
Open the item's address in your browser. For a product titled "Desk lamp", that is /products/Desk-lamp. The list of all published products is at /products.
5. Call the REST API
The REST API authenticates with an API key that belongs to an admin.
- Open Admins (under People), open your own account, and find the API keys card.
- Select Create API key and copy the key. Raytha stores only a hash, so you cannot see it again.
Check the key with the ping endpoint, then list your products:
export RAYTHA_URL=http://localhost:5001
export RAYTHA_API_KEY=paste-your-key-here
curl -s "$RAYTHA_URL/raytha/api/v1/ping" -H "X-API-KEY: $RAYTHA_API_KEY"
curl -s "$RAYTHA_URL/raytha/api/v1/contentitems/products" \
-H "X-API-KEY: $RAYTHA_API_KEY"
The ping response looks like this:
{
"success": true,
"version": "2.0.0",
"organizationName": "My Organization"
}
The list response wraps the items in result. Each item carries routePath, primaryField, isPublished and a publishedContent object with one entry per field:
{
"success": true,
"result": {
"items": [
{
"id": "mwlKKk8cfkOm8ACNQcycgQ",
"routePath": "products/Desk-lamp",
"primaryField": "Desk lamp",
"isPublished": true,
"publishedContent": {
"title": { "value": "Desk lamp", "text": "Desk lamp", "hasValue": true },
"content": { "value": "<p>A very bright lamp.</p>", "text": "A very bright lamp.", "hasValue": true }
}
}
],
"totalCount": 1
}
}
The response above is trimmed. Real items also include creationTime, draftContent, webTemplateId and similar metadata.
Your instance also serves an interactive API reference at /raytha/api.
Gotchas
- A request without a valid
X-API-KEYreturns401. - The Compose file above publishes the app on host port
5001. If something else already uses those ports,docker compose upfails to bind them. Change the host side of the mapping indocker-compose.yml. - Local file storage keeps uploads in the
raytha_user_uploadsDocker volume. Remove the volume and the files go with it. - Setup runs once. A second submission is rejected with HTTP
409and the message "Initial setup has already been completed". Add more admins from Admins.
Next steps
- Deploy with Docker: a production-shaped setup with HTTPS and a reverse proxy.
- Configuration: SMTP, file storage, limits and proxy trust.
- REST API overview and Building templates.
- First hour in the admin, written for editors.