Thank you for considering expanding CardSorter! CardSorter is a tool aimed to make card sorting accessible to any UX Researcher, UX Practitioner, Professional, or hobbyist.
The official live version of the tool can be found in: https://usability.csd.auth.gr/card-sorter/
Before starting developing make sure you are familiar, at least to a high level, with the following technologies and workflows:
| Redux (Docs | Video) |
The designer module is the main component of the application. It is here that the users will create a new card sort and will share it with their participants to complete the card sort. This is also where the analysis will happen: we show all the data collected from the various card sorts, both in aggregate and in more complex visualisations (e.g. dendrogram).
The designer module is an authenticated system: the user will need to login in order to access their study and related data.
The sorter module is the interface that the participants of the card sort will use to complete it. When a user creates a new study, they will share a link with the participants. This link will render the sorter module.
|-- Dockerfile # Used for instructing the production server how to run the client
|-- messages # Internationalisation of the app, see "Internationalisation" below
| `-- en.json # English locale
|-- public # Static files
| `-- images # Images used throughout the application
|-- src # The code of the app lives here
| |-- App.css # CSS classes for the designer & auth part of the application
| |-- Store.ts # Configuration of the Redux-Store
| |-- actions # Redux actions
| | |-- ActionStatus.ts # Enum for the status of thunk (async) actions (e.g. IS_FETCHING)
| | |-- authAction.ts # Actions related to the global authentication of the app (auth tokens)
...
| | |-- sorting # Actions for the sorting component of the app
...
| | `-- studyPageAction.ts # Actions related to the study page
| |-- app # NextJS app router, each page corresponds to a different URL in the browser
| | `-- [locale]
| | |-- create # http://localhost:3000/card-sorter/en/
| | | |-- add-cards # http://localhost:3000/card-sorter/en/create/add-cards
| | | |-- final # http://localhost:3000/card-sorter/en/create/final
| | | |-- page.tsx # http://localhost:3000/card-sorter/en/create
| | | `-- success # http://localhost:3000/card-sorter/en/success
| | |-- layout.tsx # Layout for http://localhost:3000/card-sorter/en/
| | |-- login # http://localhost:3000/card-sorter/en/login
| | |-- page.tsx # http://localhost:3000/card-sorter/en/
| | |-- register # http://localhost:3000/card-sorter/en/register
| | |-- sort # http://localhost:3000/card-sorter/en/sort
| | | |-- [id] # http://localhost:3000/card-sorter/en/sort/some_id
| | | |-- layout.tsx # Layout for http://localhost:3000/card-sorter/en/sort
| | | |-- not-found # http://localhost:3000/card-sorter/en/sort/not-found
| | | `-- thank-you # http://localhost:3000/card-sorter/en/sort/thank-you
| | `-- study # http://localhost:3000/card-sorter/en/study
| | `-- [id] # http://localhost:3000/card-sorter/en/study/some_id
| | |-- cards # http://localhost:3000/card-sorter/en/study/some_id/cards
| | |-- categories # http://localhost:3000/card-sorter/en/study/some_id/categories
| | |-- clusters # http://localhost:3000/card-sorter/en/study/some_id/clusters
| | |-- layout.tsx # Layout for http://localhost:3000/card-sorter/en/study/some_id
| | |-- page.tsx # http://localhost:3000/card-sorter/en/study/some_id
| | |-- similarity # http://localhost:3000/card-sorter/en/study/some_id/similarity
| | `-- sorting # http://localhost:3000/card-sorter/en/study/some_id/sorting
| |-- elements # Reusable elements used in the pages in the NEXTJs app router
| | |-- sorting # Reusable elements specific to the sorting component
| | `-- visualisations # Visualisation used on the study page
| |-- i18n # Setup for internationalisation
| |-- index.css # Needs to be refactored to include css resets
| |-- middleware.ts # NextJS middleware
| |-- reducers # Redux reducers
| | |-- StateSchema.ts # The schema (type) of the state for the whole application
...
| | |-- sorting # Reducers specific to the sorting component
...
| | `-- studyPageReducer.ts # Reducer for the study page
| |-- sorter.css # CSS classes for the sorter component
| `-- utils # Static, reusable, utilities
When thinking of adding a new feature, it is helpful to use this workflow:
This application uses material-symbols for rendering icons. If you’d like to add an icon to a React component, you just need to create a span with the class “material-symbols-outlined” and add as content the material icons name.
Example:
<span className="material-symbols-outlined">arrow_back</span>
One simple way to find the icon name is by:
src/utils/var.scss and should be imported in any new scss file @use "utils/var" as var;.For an example of an SCSS file take a look at src/elements/StudyItem/StudyItem.module.scss.
To enable rendering the app in different languages the following process should be followed when adding text (including hidden texts, e.g. image alt):
Example:
messages/en.json
{
"LoginPage": {
...
},
...
"StudiesListPage": {
...
"create study": "Create a study",
...
},
...
}
src/app/[locale]/study/page.tsx
import {useTranslations} from "next-intl";
export default function page() {
const t = useTranslations("StudiesListPage");
return <button>{t("create study")}</button>;
}
When using NextJS app router components (Link, redirect, usePathname, useRouter, getPathname) import them from “i18n/navigation” instead of “next/navigation”. The exported component from “i18n/navigation” will also handle routing for the internationalised context (e.g. /en/).
Example:
import {Link} from "i18n/navigation"; # not "next/navigation"
export default function page() => {
return <Link className="logo-container" href='/'>CardSorter</Link>;
}
useState) for transient UI states and unsaved changesHere is an excellent source for Redux best practices.
Happy coding!