# Lovelycode documentation

The complete public documentation for Lovelycode, a static website host. Get a site online, connect a domain, manage access and configuration, and find technical details for deployment, routing, redirects, headers and caching.

Source: https://lovelycode.app/docs (one page per section, linked from each heading)
Last updated: 11 September 2026

## [Getting started](https://lovelycode.app/docs/getting-started)

Get your website online and ready to share.

Lovelycode hosts your finished website files. Bring a portfolio, a landing page or a browser app, whether you made it yourself or with an AI agent.

### Get your files ready

You’ll need your website’s HTML, CSS, JavaScript and images, with `index.html` at the top level. If you’re working with an agent, ask it for the finished static website files, ready to upload. If your project has a build step, use the output folder from that build.

### Create your site

Create a website in the dashboard and give it a name. You’ll get a lovelyco.de address with a placeholder page while you add your files.

### Add your files and share the link

Open the site and drop in your files or folders. Upload the contents of your website folder so `index.html` is at the top level. Files go live as they arrive, with no separate publish button. Open your address to check the site, then share it.

Using GitHub or an automated build? See [Publishing](https://lovelycode.app/docs/publishing) for the other ways to send your files.

### What every site comes with

- Cloudflare’s global network and DDoS protection.
- Automatic HTTPS on your lovelyco.de address. Custom domains get HTTPS once setup is complete, with renewals handled for you.
- Your pages stay yours, with no added branding or analytics. Enabling [environment variables](https://lovelycode.app/docs/env) adds a small script to make those variables available to your code.

### Online and offline

Use the online switch in settings to pause access to your site. Visitors will see an offline notice, and your files stay in place. Switch it back on when you’re ready.

### Deleting a website

Deleting a site removes its files and frees its address for others to use. There is no undo, so download a copy first if you might want one.

## [What you can customize](https://lovelycode.app/docs/customize)

Make the site work the way you need, from its address to its error page.

### In the site’s settings

| What | How | Read more |
| --- | --- | --- |
| Name | Change it any time. It does not affect the address. | [Your address](https://lovelycode.app/docs/address) |
| Address | Pick any free `name.lovelyco.de`; the old one stops working at once. | [Your address](https://lovelycode.app/docs/address) |
| Custom domain | Point a domain you own at the site, with HTTPS handled for you. Paid plan. | [Custom domains](https://lovelycode.app/docs/custom-domains) |
| Online or offline | Pause visitor access while keeping your files in place. | [Getting started](https://lovelycode.app/docs/getting-started) |
| Passwords | Up to ten, each covering the whole site or one folder, each with its own sign-in duration. | [Password](https://lovelycode.app/docs/password) |
| Files source | Drag and drop, a GitHub repository and branch, or a deploy key for your CI. | [Publishing](https://lovelycode.app/docs/publishing) |
| Environment variables | Public values and secrets, with the hosts each secret may be sent to. | [Environment variables](https://lovelycode.app/docs/env) |
| Delete | Permanently remove the site and release its address. | [Getting started](https://lovelycode.app/docs/getting-started) |

### With a file in your site

| What | How | Read more |
| --- | --- | --- |
| Your own 404 page | Add `404.html`. It is served with a real 404 status. | [Paths and routing](https://lovelycode.app/docs/routing) |
| Single-page app routing | Add `200.html`. Unknown addresses are answered with it, status 200. | [Paths and routing](https://lovelycode.app/docs/routing) |
| Redirects | Add `_redirects`, Netlify format, one rule per line. | [Redirects](https://lovelycode.app/docs/redirects) |
| Response headers | Add `_headers`: security policies, CORS, content disposition, anything starting with `X-`. | [Headers](https://lovelycode.app/docs/headers) |
| Browser caching | Set `Cache-Control` in `_headers` for files with fingerprinted names. | [Caching](https://lovelycode.app/docs/caching) |
| Search engine preference | A `<link rel="canonical">` in each page chooses which address is indexed. | [Custom domains](https://lovelycode.app/docs/custom-domains) |

HTTPS and hosting on Cloudflare’s global network are handled for you.

## [Your address](https://lovelycode.app/docs/address)

Choose a lovelyco.de address for your website.

Every site gets an address on lovelyco.de, made from its name: a site called Hello becomes `hello.lovelyco.de`, or `hello-1.lovelyco.de` if that is already taken.

### Changing it

Enter a new address in your site’s settings. We’ll check availability as you type. Changing it keeps your files in place; changing just the site’s name leaves the address as it is.

After you save a new address, update any links you’ve shared. The old address stops working, has no redirect and becomes available for someone else to use.

### Choosing an address

- An address is lowercase letters, numbers and single hyphens, up to 50 characters.
- Some words are reserved and cannot be used: system words such as `admin`, and brand names.

## [Custom domains](https://lovelycode.app/docs/custom-domains)

Use your own domain, with HTTPS managed for you. Available on a paid plan.

### Connect your domain

Add your domain in the site’s settings. Then open the DNS settings where you manage your domain and add the two records below. DNS records tell browsers where to find your website.

Both `mysite.com` and `www.mysite.com` will work. The address you enter in Lovelycode is the main one; the other redirects to it.

*DNS at your registrar*

```
Type    Name    Value
-----   -----   --------------------
CNAME   @       custom.lovelyco.de
CNAME   www     custom.lovelyco.de
```

- If your registrar does not allow a CNAME on the root domain (the `@` record), use an ALIAS or ANAME record instead.
- Do not delete your other DNS records. Your MX records, for instance, are what deliver your email.

### Wait for HTTPS to be ready

Once the DNS records are live, we set up your HTTPS certificate and handle future renewals. You may see a browser security warning while setup is still in progress. Wait for it to finish before sharing the domain; your lovelyco.de address is available in the meantime.

### Search engines

Your lovelyco.de address keeps working alongside your domain, without redirecting. To tell search engines which address you prefer, add a canonical link in each page’s `<head>`. Use that page’s full address, for example:

*in the <head> of each page*

```
<link rel="canonical" href="https://mysite.com/about">
```

### If your subscription ends

Your domain stops pointing at the site, and visitors to it see a security warning. Nothing is deleted and your DNS records stay correct, so subscribing again restores it automatically.

## [Password](https://lovelycode.app/docs/password)

Share a site or folder with a password. Available on every plan.

Add a password in your site’s settings, choose the whole site or a folder to protect, and share the password with your visitors. Pages, images and downloads in that area all require it.

Choose how long visitors stay signed in: a day, a week, a month or a year. They’ll see a password form when they first visit.

### Check the visitor experience

Open the live site in a new tab to try the password form. The preview in your dashboard gives you access without entering a password.

### Several passwords

You can add up to ten passwords per site, each for a different area. A folder such as `/portfolio` can have its own password. Visitors need that folder’s password to open it, even if they already entered the password for the whole site.

Protection also covers alternate page addresses. A password on `/portfolio` covers `/portfolio.html` and `/portfolio/index.html` too.

### Manage access

- Change a password to sign out everyone who used the old one. Share the new password with anyone who should keep access.
- A password only works on the site it was set for. If you type the same password for two addresses, they are still two separate passwords: changing or removing one does not affect the other.
- Use the eye beside a saved password to view it. To change it, edit the field and save.
- Passwords set before 9 September 2026 cannot be displayed. Enter a new password to replace one.

### Sharing a password

Visitors share a password rather than having individual accounts, so they can pass it on and you cannot identify them separately. Use this for controlling access to a site, rather than storing sensitive data. To pause access for everyone, switch the site offline in settings.

## [Publishing](https://lovelycode.app/docs/publishing)

Upload your files, connect GitHub or deploy from your build tools.

Send your finished website files to Lovelycode and they’re online. Updates become available as files arrive; removing a file removes it from the live site too. If your project needs a build, run it first and send the output.

### Choose how to upload

| Source | How it works | File editor |
| --- | --- | --- |
| Drag and drop | Drop files or whole folders into the dashboard. A zip file is stored as a file, not unpacked, so drop the folder itself. | Stays editable |
| GitHub | Connect a repository and a branch. Every push to that branch updates the site. | Read only |
| Your own CI | Create a deploy key and have your pipeline send the build output as a zip. | Read only |

With GitHub or a deploy key connected, make changes in your source project. Files in the dashboard are read only while that connection is active. Disconnect it to manage files in the dashboard again.

### Versions

Each publish keeps a complete copy of your site as a version, and visitors always see one whole version at a time: a change with several files never appears half applied. The five most recent versions are kept, plus the one that is live, and they do not count toward your storage.

By default, the dashboard publishes a new version 20 seconds after your last change. You can pause the countdown and publish when you are ready, or turn automatic publishing off in your site’s settings. Changes then wait in a draft that only you can open, at an address the dashboard gives you, until you press Publish.

- Open Versions in the dashboard to see every version, preview one, or restore one. Restoring makes that version live right away and puts its files back in your editor.
- A draft or version preview address works for an hour from the moment the dashboard hands it to you, so you can share it with someone for a quick look.
- GitHub syncs and deploys create versions too, so a bad push is one Restore away from being undone.

### Upload from your computer

Open your site in the dashboard and drop in the files or folders. Put `index.html` at the top level. If you have a zip, unzip it first: dashboard uploads keep zip files as downloads rather than extracting them.

### Connect GitHub

Choose GitHub in your site’s file source settings, then select a repository and branch. Push changes to that branch to update the site. The repository should contain files ready to serve; Lovelycode does not run a build. For projects that need one, use your build pipeline and a deploy key.

### Deploying from your own CI

Create a deploy key in your site’s settings and store it as a secret in your CI system. Each key belongs to one site. If you need to replace it, your other sites keep their own keys.

The script below requests an upload URL, uploads a zip and applies the update. Zip the contents of your build folder so `index.html` is at the top level. Your site’s settings include a version filled in with its details.

*deploy.sh*

```
# Needs jq. Zip the CONTENTS of your build folder, so index.html is at the top.
(cd dist && zip -qr ../site.zip .)
SIZE=$(wc -c < site.zip)

# 1. Ask for a one-time upload URL. The size is signed into it, so it must be exact.
DEPLOY=$(curl -fsS -X POST https://lovelycode.app/api/v1/sites/$SITE_ID/deploys \
  -H "Authorization: Bearer $LOVELYCODE_DEPLOY_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"size\":$SIZE}")

# 2. Upload the archive straight to storage. Raw body, not multipart.
curl -fsS -X PUT "$(echo "$DEPLOY" | jq -r .deploy.upload_url)" \
  -H "Content-Type: application/zip" \
  --data-binary @site.zip

# 3. Publish. Unchanged files are skipped, files you removed are deleted.
curl -fsS -X POST https://lovelycode.app/api/v1/sites/$SITE_ID/deploys/$(echo "$DEPLOY" | jq -r .deploy.id)/commit \
  -H "Authorization: Bearer $LOVELYCODE_DEPLOY_KEY"

# A 429 or 409 means another deploy is too close or still running. Both are safe to
# retry after a few seconds; anything else will not improve with waiting.
```

On commit we compare the archive with what is already on the site. Files that have not changed are skipped, files you removed are deleted, and deploying an identical build changes nothing at all.

To create websites from a script as well, or to let an agent do the whole thing, see the [API](https://lovelycode.app/docs/api).

## [API](https://lovelycode.app/docs/api)

Create and publish websites from a script or an agent.

The API lets a script, a CI pipeline or an AI agent create a website and publish files to it, with one token for your whole account. It is available on paid plans.

### Ask your agent

If you use Claude Code or another agent that can run commands, create a token in your account settings, set it as `LOVELYCODE_TOKEN` in the agent’s environment, and ask for what you want:

*What to say*

```
Publish the website in ./site to Lovelycode as "My Portfolio".
The API is described at https://lovelycode.app/llms.txt and the token is in $LOVELYCODE_TOKEN.
Tell me the address when it is live.
```

Everything on these pages is also served as plain text at `/llms.txt`, so an agent can read it directly. Keep the token in the environment rather than in the conversation, so it stays out of the transcript.

### Create a token

Open Account, then API, and press Create token. Give it a name that says where it lives, choose how long it lasts, and copy it: it is shown once. Revoke it from the same place if it leaks or you stop using it.

A token can create websites and publish files to websites that take their files from the API. It cannot read files or settings, delete a website, or touch a website whose files are managed in the dashboard or synced from GitHub. A website created through the API is read only in the dashboard while its deploy key exists, and publishes automatically unless you turn that off in its settings.

### Create a website

*create.sh*

```
curl -fsS -X POST https://lovelycode.app/api/v1/sites \
  -H "Authorization: Bearer $LOVELYCODE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"My Portfolio"}'

# → { "site": { "id": "…", "url": "https://my-portfolio.lovelyco.de", … }, "deploy_key": "lc_deploy_…" }
```

Add `"subdomain"` to the body to choose the address yourself; without it, one is made from the name. The response holds the website’s id and address, plus a deploy key. The key can publish to that one website and nothing else, which is what a CI pipeline should hold. Either the token or the key works for the steps below.

### Publish files

A publish is three calls: ask for an upload address, upload a zip of your files, then commit. Zip the contents of your folder so `index.html` is at the top level. Needs `jq`.

*deploy.sh*

```
# Needs jq. Zip the CONTENTS of your build folder, so index.html is at the top.
(cd site && zip -qr ../site.zip .)
SIZE=$(wc -c < site.zip)

# 1. Ask for a one-time upload URL. The size is signed into it, so it must be exact.
DEPLOY=$(curl -fsS -X POST https://lovelycode.app/api/v1/sites/$SITE_ID/deploys \
  -H "Authorization: Bearer $LOVELYCODE_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"size\":$SIZE}")

# 2. Upload the archive straight to storage. Raw body, not multipart.
curl -fsS -X PUT "$(echo "$DEPLOY" | jq -r .deploy.upload_url)" \
  -H "Content-Type: application/zip" \
  --data-binary @site.zip

# 3. Publish. Unchanged files are skipped, files you removed are deleted.
curl -fsS -X POST https://lovelycode.app/api/v1/sites/$SITE_ID/deploys/$(echo "$DEPLOY" | jq -r .deploy.id)/commit \
  -H "Authorization: Bearer $LOVELYCODE_TOKEN"

# A 429 or 409 means another deploy is too close or still running. Both are safe to
# retry after a few seconds; anything else will not improve with waiting.
```

Files that have not changed are skipped, files you removed are deleted, and an identical build changes nothing. Each publish makes a version, so a mistake is one Restore away in the dashboard. Publish the same way to update the website later.

### Endpoints

| Call | What it does |
| --- | --- |
| `POST /api/v1/sites` | Creates a website. Body: `name`, optional `subdomain` and `description`. Returns the site and a deploy key. |
| `POST /api/v1/sites/{id}/deploys` | Starts a publish. Body: `size`, the exact byte length of the zip. Returns an upload address, valid for 15 minutes. |
| `POST /api/v1/sites/{id}/deploys/{deployId}/commit` | Applies the uploaded zip and publishes a version. |

Send the token as `Authorization: Bearer` on every call. A site’s deploy key works in place of the token for its own deploys.

### Errors

Every error is JSON with a sentence in `error` and a stable `code`. When `retryable` is true, wait a few seconds and try again; anything else will not improve with waiting.

| Code | Meaning |
| --- | --- |
| `unauthorized` | The token is missing, wrong, revoked or expired. The message says which. |
| `plan_required` | The account is not on a paid plan. |
| `invalid_request` | Something in the body is missing or the wrong shape. The message says what. |
| `forbidden` | A deploy key was used where an account token is needed, or the token lacks the scope. |
| `not_found` | No website with that id belongs to this account, or the archive was not uploaded before committing. |
| `subdomain_taken` | The address you chose is in use. Pick another, or leave it out to have one made from the name. |
| `files_source_conflict` | The website’s files come from the dashboard or GitHub. Create a deploy key in its settings to publish through the API. |
| `deploy_running`, `rate_limited`, `deploy_conflict` | Another publish is in progress, too recent, or landed while yours was publishing. All retryable. |
| `archive_invalid`, `archive_too_large` | The zip has a bad path, no `index.html` at the top level, or is over 100 MB. Zip the folder’s contents, not the folder. |
| `website_limit_reached`, `storage_limit_reached` | A plan limit. Delete something or upgrade. |
| `internal` | Our side. Try again in a minute; if it persists, tell us. |

### What the API does not do

- Read anything. There is no call that returns your files, settings or passwords, so a leaked token cannot take anything out.
- Delete a website or change its settings. Those stay in the dashboard, behind your login.
- Edit single files. A publish is always a whole set of files, which is what makes a version.
- Run more than one publish per website at a time, or two within ten seconds.

## [Environment variables](https://lovelycode.app/docs/env)

Change configuration and API keys without uploading your site again.

Environment variables hold values your code uses, such as an API address. Add them in your site’s settings, then use their names in JavaScript. You can update the values later without rebuilding or uploading your files again.

### Add a variable

Choose a name using uppercase letters, digits and underscores, and enter its value. For example, add a public variable named `API_BASE` with your API’s address. Your code can then use it like this:

*index.html*

```
<script type="module">
  // API_BASE is defined in this site's settings.
  const res = await fetch(API_BASE + '/products')
  console.log(await res.json())
</script>
```

Sites with environment variables get a small script at the top of their HTML to make the variables available. Sites without variables do not get this script.

### Public or secret

| Kind | In the browser | Use it for |
| --- | --- | --- |
| Public | The real value | An API base URL, an OAuth client id, a publishable key |
| Secret | A placeholder, never the value | Anything you would not paste into a public repository |

### Using a secret

Add the API’s host to the secret’s allowed list, then use the variable in your request. Lovelycode replaces the placeholder with the real value when sending the request to that host. The value stays out of the browser.

*checkout.js*

```
// PAYMENTS_KEY is a secret. api.example.com is on the allowed list.
await fetch('https://api.example.com/charge', {
  method: 'POST',
  headers: { Authorization: 'Bearer ' + PAYMENTS_KEY },
  body: JSON.stringify({ amount: 500 })
})
```

You choose which hosts each secret may be sent to. A secret is never sent anywhere else, and one with no allowed host cannot be used at all. If an API receives the literal text `{{PAYMENTS_KEY}}`, its host is missing from the list.

### Limits

| Limit | Value |
| --- | --- |
| Variables per site | 50 |
| Value length | 2 KB |
| Allowed hosts per site | 20 |

## [Paths and routing](https://lovelycode.app/docs/routing)

Set up page addresses, app routes and a custom 404 page.

Addresses do not need `.html`: a visit to `/about` is answered by `about.html` or by `about/index.html`, whichever you have.

*what answers what*

```
your files                addresses
------------------------  ------------------------------------------
index.html                /
about.html                /about        (/about/ redirects here)
blog/index.html           /blog/        (/blog redirects here)
blog/first-post.html      /blog/first-post
assets/app.css            /assets/app.css
404.html                  anything missing, with a 404
200.html                  anything missing, with a 200
```

### Single-page apps

If your app handles its own routes, name its entry file `200.html`. Any page address that does not match a file is answered with that file and a 200 status, so reloading `/settings/billing` starts your app instead of showing a 404.

### Your own 404

Add a `404.html` and it is shown for any missing address, with a real 404 status. If a site has both `404.html` and `200.html`, the `200.html` is used, since an app has to see the address before it can decide the address is missing.

These fallbacks apply only to page addresses, meaning ones with no extension or ending in `.html` or `.htm`. A missing image or stylesheet gets a plain 404, never your `200.html`.

### Trailing slashes

For `about.html`, `/about/` redirects to `/about`. For `about/index.html`, `/about` redirects to `/about/`. This keeps relative links and images resolving from the right place.

## [Redirects](https://lovelycode.app/docs/redirects)

Send visitors from an old address to a new one.

Add a file named `_redirects` at the top level of your site. Each line gives an old path and its destination. The format supports common Netlify redirect rules, with the differences listed below.

*_redirects*

```
# a page that moved
/old-page            /new-page

# a whole section. * matches the rest, :splat puts it back.
/blog/*              /articles/:splat

# one segment, by name
/team/:name          /people/:name

# a temporary redirect
/sale                /products/summer     302

# retiring old CMS links: ?id=42 becomes /products/42
/store   id=:id      /products/:id

# redirect to another website
/discord             https://discord.gg/example
```

- One rule per line: the old path, the new one, and optionally a status code. Without one the redirect is a 301; 302, 303, 307 and 308 are also accepted. Anything after `#` is a comment.
- The first matching rule wins, so put specific rules above wildcards. A trailing slash makes no difference: a rule for `/about` also matches `/about/`, and `/docs/*` also matches `/docs` itself.
- Query parameters that the rule does not use are kept on the new address, so a `?utm_source` survives the redirect.

### When rules run

An existing file takes priority over a redirect. If you’re moving a page, remove the file at the old address so its redirect can run. Redirects are checked before the `200.html` and `404.html` fallbacks.

### Not supported

- Rewrites with status 200, which fetch another address and serve it under yours.
- Forced rules, written with `!`, that override an existing file.
- Conditions on the visitor’s country or language. A rule that has one is skipped entirely rather than applied to everyone.
- A source path that mixes `*` with `:name`, or that contains a `?`. To match on a query parameter, use the `key=:value` form shown above.

### Limits

| Limit | Value | If you cross it |
| --- | --- | --- |
| File size | 64 KB | The whole file is ignored |
| Rules read | 500 | The rest are not read |
| Destination length | 2 KB | That rule is skipped |

Like every file in your site, `_redirects` is public: anyone can read it at `/_redirects`.

## [Headers](https://lovelycode.app/docs/headers)

Set response headers for security, downloads and browser behaviour.

If your site needs custom HTTP headers, add a `_headers` file at the top level. It uses the path-and-header format from Netlify and Cloudflare Pages. Start with the rules your site needs from these examples:

*_headers*

```
# everything on the site
/*
  X-Frame-Options: DENY
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=()

# fingerprinted assets can be held for a year
/assets/*
  Cache-Control: public, max-age=31536000, immutable

# one segment, by name
/downloads/:file
  Content-Disposition: attachment

# a WebAssembly app that needs threads
/app/*
  Cross-Origin-Opener-Policy: same-origin
  Cross-Origin-Embedder-Policy: require-corp
```

- Each rule is a path on its own line, followed by its headers indented underneath, one `Name: value` per line. A `*` at the end of a path covers everything below it; `:name` stands for one path segment. The indentation matters: a header line that is not indented ends the rule.
- When several rules match an address, all of them apply, top to bottom. If two set the same header, the lower one wins.
- A rule for `/about` covers that page however its address is spelled, `/about.html` and `/about/index.html` included.

### Where they apply

Your headers are added to the files you shipped: pages and assets served with a 200, and the 304 a browser gets when it re-checks one. They are not added to redirects, to 404 responses, to the password form or to the offline page. The editor preview does not apply them either, so check them on the live address.

### Cache-Control

The default caching settings make browsers check for updates before reusing files. You can override `Cache-Control` for files whose names change with their contents, such as `app.4f9c2b.css`. A `max-age` lets browsers reuse a file until that time expires. See [Caching](https://lovelycode.app/docs/caching) for an example. HTML keeps `no-transform`, and password-protected addresses keep `private`.

### Supported headers

Most response headers: `Content-Security-Policy`, `X-Frame-Options`, `Permissions-Policy`, `Referrer-Policy`, the `Cross-Origin-*` headers, the `Access-Control-*` headers, `X-Robots-Tag`, `Link`, `Content-Disposition`, `Content-Type`, and anything starting with `X-`.

### Headers managed by Lovelycode

| Header | Why |
| --- | --- |
| Set-Cookie, Clear-Site-Data | They reach across all of lovelyco.de, not just your site |
| Location, Refresh | Use a _redirects file to set up redirects |
| Strict-Transport-Security | A promise about the address that would outlive your site on it |
| ETag, Content-Length, Content-Encoding | They describe the response itself, which we produce |

Unsupported headers are skipped without an error; other headers in the rule still apply. Headers set by Lovelycode cannot be removed.

### Limits

| Limit | Value | If you cross it |
| --- | --- | --- |
| File size | 64 KB | The whole file is ignored |
| Paths read | 100 | The rest are not read |
| Headers per path | 32 | The rest are not read |
| Value length | 8 KB | That header is skipped |

Like every file in your site, `_headers` is public: anyone can read it at `/_headers`.

## [Caching](https://lovelycode.app/docs/caching)

Keep visitors up to date, with caching handled for you.

You don’t need to clear a cache after updating your site. By default, browsers check for updates before reusing a saved file. When a file is unchanged, they can reuse their copy without downloading it again.

Cloudflare’s global network helps deliver your files close to your visitors. Caching works automatically, so most sites can use the defaults.

### Cache files with versioned names for longer

If your build gives files fingerprinted names, such as `app.4f9c2b.css`, the name changes whenever the content does, so browsers can safely keep those files for a year. Set that in `_headers`. Never do it for HTML pages, or for any file whose name stays the same between builds.

*_headers*

```
/assets/*
  Cache-Control: public, max-age=31536000, immutable
```

## [Limits](https://lovelycode.app/docs/limits)

Check what you can host and the limits to keep in mind.

### What you can host

Lovelycode hosts static files: HTML, CSS, JavaScript, images and other assets. Your JavaScript runs in the browser and can connect to external APIs and services.

Server-side code such as PHP, Node, Python, Ruby or Go needs to run elsewhere. Lovelycode does not run API routes, scheduled jobs or databases.

### Bandwidth

We do not count bandwidth. A viral day costs you nothing extra.

Each site has a fair-use allowance of 10 million requests a month. A page view can make several requests, depending on its files. If your site reaches the allowance, we’ll email you rather than switch it off.

### Storage and sites

Storage is counted per account and shared across all your sites, not allotted per site. How much storage you have, and how many sites, depends on your plan.

### Technical limits on every plan

| Item | Limit |
| --- | --- |
| Deploy archive | 100 MB, and 100 MB once unzipped |
| _redirects | 64 KB, first 500 rules, 2 KB per destination |
| _headers | 64 KB, first 100 paths, 32 headers each, 8 KB per value |
| Environment variables | 50 per site, 2 KB each, 20 allowed hosts |

### Updates and recovery

Files update one at a time during a deploy. A visitor loading your site during that update may briefly receive a mix of old and new files. There is no one-click rollback, so keep a copy of your previous build if you may need to restore it.

### Traffic and analytics

Lovelycode does not provide request logs or traffic graphs. You can add your preferred analytics to your own pages.

Something wrong or missing here? Write to hello@lovelyco.de.

## [Fixing things](https://lovelycode.app/docs/fixing)

A few checks to help you get back on track.

| What you see | What to try |
| --- | --- |
| A page 404s and the file is there | Check that the file is in the expected folder and that the link matches its name. For example, `about.html` at the top level answers `/about`. See [Paths and routing](https://lovelycode.app/docs/routing). |
| Reloading a route in my app 404s | Name your entry file `200.html`. |
| A redirect does not fire | Check whether a file still exists at the old address. Files take priority over redirect rules. See [Redirects](https://lovelycode.app/docs/redirects). |
| One redirect rule is ignored | Check for unsupported syntax, such as `*` together with `:name`, a `?` in the source path, or a country or language condition. See [Redirects](https://lovelycode.app/docs/redirects). |
| A header is not on the response | Custom headers are only added to files served normally, never to redirects, 404s, the password form or the editor preview. Check on the live address, not in the editor. |
| One header is missing, the rest are there | Check that its line is indented and the header is supported. See [Headers](https://lovelycode.app/docs/headers). |
| I updated a file and still see the old one | Check that the uploaded file includes your change, then look for a custom `Cache-Control` rule in `_headers` that lets browsers keep an older copy. See [Caching](https://lovelycode.app/docs/caching). |
| My API receives `{{MY_KEY}}` | Check that the API’s host is on the secret’s allowed list. See [Environment variables](https://lovelycode.app/docs/env). |
| A variable is undefined | Check the name: uppercase letters, digits and underscores only. The variables are defined at the top of every HTML page, so any script a page loads can use them. |
| A deploy fails on commit | Check the error message first. One common cause is the archive structure: `index.html` needs to be at the top level. Zip the folder’s contents rather than the folder itself. |
| My custom domain shows a security warning | Check your DNS records and domain status in settings. HTTPS setup may still be in progress. Also check that your paid subscription is active. See [Custom domains](https://lovelycode.app/docs/custom-domains). |
| My site says it is offline | It was switched off in the site’s settings. Switch it back on there. |

Still stuck? Email hello@lovelyco.de with your site’s address and what you’re seeing.
