Navigated to /docs/nokkio-image.

@nokkio/image

Handling image uploads the Nokkio way.

Nokkio aims to provide abstractions over common headaches of web development. Uploading images is one such task–a long-solved problem that requires a lot of setup every time you need to add it to your project.

When your data models include images, Nokkio automatically wires up all the necessary bits to perform the upload, validate the image, and returns rich data about the image that can be used with @nokkio/image to provide images automatically resized and optimized for your application, all served via a CDN.

Preparing the model

For the following examples, we'll assume you have a User model in your application that you would like to add an optional avatar field to. First step is to setup the field in your model.

const User = defineModel('User', {
  username: types.string().unique(),
  password: types.password(),
  avatar: types.image(null),
});

For more about types.image(), see the documentation.

Updating the form

Allowing the user to upload a photo is then as simple as adding a file input to the form. Note that in this example we are only updating the avatar field, but you can update image fields and other field types at the same time in a single update.

import { useAuth } from '@nokkio/image';
import { useForm, Input } from '@nokkio/forms';

export default function UserAvatarForm() {
  const { user } = useAuth();
  const { Form } = useForm(user);

  return (
    <Form>
      <Input type="file" name="avatar" />
    </Form>
  );
}

As you can see, you update an image like any other field. During the update, Nokkio does the following:

  1. Validates the image metadata to ensure the image is of the correct type, dimensions, and size.
  2. Uploads the image to cloud storage.
  3. Sends the appropriate metadata to Nokkio's data backend.

Using the image

Once a data record has an image, you can use it inside your components. For example, if we had a component to display the user's avatar:

import { useAuth } from '@nokkio/auth';
import { Img } from '@nokkio/image';

export default function UserAvatar() {
  const { user } = useAuth();

  if (!user.avatar) {
    // Show a default avatar or something else.
    return null;
  }

  return <Img
    image={user.avatar}
    width={300}
    height={300}
    crop />;
}

The Img component receives an image object and creates a img tag with a src that will automatically fetch a resized image to match the given parameters. In this example, it will be a cropped 300 x 300 version of the user's avatar.

If we were to omit the crop property, it would return a copy of the avatar that is proportionally sized to fit within that 300 x 300 box.

Responsive layouts

If you don't provide an explicit width or height to the Image component, Nokkio will instead read the dimensions of the image in its current layout context and automatically supply the proper image. Be sure to give the image some sort of cue on how it should be sized within its container. For example:

<Img
  image={album.photo}
  style={{width: '100%'}}
/>

Image properties

When your model has an image field, the returned data is an object with several properties:

const { user } = useAuth();
console.log(user.avatar);
// Outputs:
// {
//   name: 'filename.jpg',
//   type: 'image/jpeg',
//   width: 1200,
//   height: 800,
//   size: 1280000
// }

Use with @nokkio/magic

When querying models that have images, you can query on the properties of the image. For example, imagine we had a Photo model in our schema:

const Photo = defineModel('Photo', {
  file: types.image(),
});

When fetching photos, we can limit the results based on the image type, for example:

const { photos } = usePhotos({
  filter: {
    'file.type': 'image/jpeg',
  },
});

Similarly, we can order the photos by filename:

const { photos } = usePhotos({
  sort: 'file.name',
});