Skip to content

We would like to use cookies to understand how this site is used. The site works the same either way. Privacy policy

DemoThis banner is a demo and part of the theme. This demo site sets no cookies and tracks nothing.

Service integrations

Guides

3 min read

How to connect a form service, a newsletter provider and checkout links to the theme.

Nightgrid is a static site with no server code. Forms, newsletter sign-ups and payments work by pointing the theme at a service you choose.

The theme was not tested against any particular service. Where this page names one, it is an example; the provider’s own documentation is the authority on its addresses and settings.

1. Contact form

As shipped, the contact form is a preview: it is shown with a short note, its button checks the fields, and nothing a visitor types is sent anywhere. To connect it, give it the address a form service gives you. Formspree, Basin and Getform are examples of such services.

Either set the address in .env (or in your host’s build settings):

bash
PUBLIC_CONTACT_FORM_ACTION=https://example.com/your-form-endpoint

or write it in src/data/contact.ts:

ts
form: {
  action: 'https://example.com/your-form-endpoint',
  // ...
},

The variable is read when the site is built, so build again after changing it.

What the form does. It is an ordinary HTML form that sends a POST request to that address, with the fields name, email, topic, message and leave_blank. The browser then shows whatever the service answers with. So the service must accept a plain form post and send the visitor on to a page.

The thanks page. Once the form has an address, the theme builds /contact/thanks/. Set your service to send visitors there after a message. If the service reads that address from a form field, uncomment redirect: 'redirect' in form.fields in src/data/contact.ts (and change the name to the one your service expects): the form then sends the full address of the thanks page in a hidden field.

Tip

leave_blank is a trap field that people do not see and simple programs fill in. Dropping messages that arrive with it filled in is the job of your form service: some expect a field name of their own, so check its documentation and rename the field in form.fields.honeypot in src/data/contact.ts.

To leave the form out of the page, delete the form block in src/data/contact.ts.

2. Newsletter sign-up

Both footers show an email field and a button (src/components/chrome/NewsletterForm.astro). As shipped it is a preview: the field and the button do nothing, and a line under them says “Not connected yet. Nothing is sent.”

To connect it, either set the address in .env:

bash
PUBLIC_NEWSLETTER_FORM_ACTION=https://example.com/your-newsletter-endpoint

or write it in src/site.config.ts:

ts
footer: {
  newsletter: {
    text: 'Product updates and new features, a few times a year.',
    action: { label: 'Subscribe', href: 'https://example.com/your-newsletter-endpoint' },
  },
  // ...
},

The variable wins when both are set.

What the field does. With an address it becomes an ordinary HTML form that sends a POST request with one field, email. The browser then shows whatever the provider answers with. Use the address your provider gives for a plain HTML form, one that answers with a page or sends the visitor on to one.

Caution

Not every provider’s form address is made for a plain HTML form. Loops is one example: its documentation (loops.so/docs/forms/custom-form, read on 2026-10-14) says the address answers with JSON and recommends sending the form with JavaScript. With the theme’s plain form, a visitor would be shown that JSON after subscribing. For a provider like that, add a script of your own that sends the form and shows a message.

To remove the sign-up, empty both footer.newsletter.text and footer.newsletter.action.label.

A plan’s button is a link. It can be a page of your own or a checkout link from a payment provider (a hosted payment page, for example). A plan can have one link for monthly and one for yearly billing; the switch on the pricing cards changes which one the button opens.

ts
// src/data/pricing.ts
{
  name: 'Team',
  price: '$12',
  priceYearly: '$9',
  summary: 'More history, more tools and a scheduled digest.',
  features: ['Unlimited connected tools', '12 months of history', 'Weekly email digest'],
  cta: {
    label: 'Choose Team',
    href: 'https://example.com/checkout/team-monthly',
    hrefYearly: 'https://example.com/checkout/team-yearly',
  },
  featured: true,
},

How it works:

  • The page is built with the monthly prices and the monthly links, so it is complete without JavaScript.
  • When a visitor picks the other period, src/scripts/billing.ts changes the prices shown and the address of each plan button. A plan without hrefYearly keeps its one link.
  • The change is written to a role="status" line that screen readers read out.

4. Analytics

See Analytics and cookie consent.

5. Publishing

See Deployment and custom domains.

↑↓navigate↵openEscclose