This is the system to manage the historic portal of Cybernetic Society (CYB), the institute association at the Department of Computer Science at the University of Oslo. It's implemented using Next.js, Sanity, TypeScript, vanilla-extract, and Algolia, and produces a static website that lives at historie.cyb.no.
- Next.js is a React framework that gives us a set of features and guidelines
- Sanity is a headless CMS that holds all of our data
- TypeScript is a superset of JavaScript, which amongst others gives us types, which prevents us introducing a lot of buggy code
- vanilla-extract is a way of writing CSS with TypeScript
- Algolia is a headless search engine, that integrates with Sanity so that we can index our data and offer a search feature on our webpage
We use Node Version Manager to ensure that we use the same version
when developing the portal. Make sure to run nvm use
before running any node commands.
Rename the .env.test
file to .env
and store the environment variables that Next and Sanity will
use to pull data from the Sanity API. You can get or create the tokens, ids, and secrets from
manage.sanity.io.
Once those env variables are ready, you can run the following commands to get Next's development server up and running:
npm install
# Run the frontend
npm run dev
# Run the Studio
npm run start:sanity
# Generating types for Sanity schemes
npm run generate:types
The website will be running at http://localhost:3000
, the Studio will run at
http://localhost:3333
. The types need to be generated after changes in Sanity schemes.
The main structure that the different files are located in looks like this:
- components // React components
- contexts // React contexts
- lib // Various utility functions
-- api // All functions related to the Sanity API
- pages // Next.js pages
- public // Files that will be copied into the static website
- studio // Sanity Studio
-- schemas // Sanity Schemas
One way of understanding how this works is to look at the workflow when setting up a new feature.
You probably want to start describing the data you need. To do this, we need to tell Sanity the
structure of this data by adding one or more schemas to
studio/schemas
. You can work with this data by running Sanity Studio.
Once your happy with your data, remember to generate types for the schemas by running:
npm run generate:types
When you have data to test with, you probably want to present this in the UI somehow.
To do this we need to hook up one or more GROQ
queries in lib/api
. These are then tied into pages
, where we tell Next.js that these queries
should be run when compiling the site into a static webpage.
The data is then funneled into the various pages, that consists of React components. Depending on
the complexity of the functionality you might need to implement React contexts and React hooks
(which we have none of currently, but would be located in hooks
when we need them) too.
If you want the data to be searchable via the search feature, you also want to hook this data up
to Algolia by adding it to lib/algolia.ts
.
All data is structured into Sanity schemas in studio/schemas
. These can be categorized into the
following features:
-
Pages: Administrators can create pages via the studio, which can be have parent pages. Currently we only support one level of parent (e.g.
foo/bar
, but notfoo/bar/baz
), but we can expand this if needed.The main part of pages are the body section, which can consists of multiple components:
buttonComponent
: A simple link (that looks like a button)buttonsComponent
: A group of links (that looks like buttons)dataComponent
: A special component that must be tied into special pages (this will eventually be phased out, so ignore it)fileComponent
: Allows uploading a file that are linked to from the pageimageComponent
: A single picture (usingphoto
)subpagesComponent
: List pages that have the current page as a parent pagetextComponent
: A block of text (usingblockContent
)
-
Pictures: Photo albums (
album
) that contains pictures (photo
). Photos can be described using larger texts (blockContent
). -
Groups: Groups of people, using
group
,groupComposition
, 'membership', andperson
. A person should have a title in the group, otherwise it will default to "Medlem". -
Honorary Members: A list of people that have received an honorary membership by CYB. Using the
person
schema. -
History: A timeline of all events that have happened in CYB's history. The main schema for this feature is
event
, but pages also have fields that allow them to optionally be added to the timeline. Finally, groups and honorary members are also added to the timeline.event
are the only one to be using thesource
schema though, where administrators can link an event to sources, be they on the internet or in a book.An event can be assigned as a minor or major event, which are presented a bit differently in the timeline. This option is also available for pages.
-
Site settings: This schema is a bit special, since we only need one for the whole site. So in the studio this is hardcoded to point to the single instance we need. This feature uses the
siteSettings
,navigation
andnavigationItem
schemas, and allows manipulating global features, like the menus.