We build Next.js applications with Tailwind CSS as our CSS authoring framework. Some examples here may contain Tailwind CSS specific tips, but for the sake of practicality, we will include everything here.
- Page containers
- Custom fonts
- Blocks
Money.jsx
componentLocalDate.jsx
component- Login
- Authenticated pages
- Authenticated API routes
In some cases wherein a mock-up contains a specific max-width, you can
instead modify Tailwind's existing container
class.
In your tailwind.config.js
module.exports = {
theme: {
container: {
center: true,
padding: '2em',
screens: {
lg: '1024px',
xl: '1280px',
},
},
},
variants: {
extend: {},
},
plugins: [],
}
Then in your JSX file:
<div className='container'>
...
</div>
If a font name has spaces in it, you will need to wrap it in quotes.
module.exports = {
theme: {
extend: {
fontFamily: {
sans: ['"Voyage Regular"', '"Playfair Display"'],
},
},
},
variants: {
extend: {},
},
plugins: [],
}
A block is a "row" of element. Most commonly found in landing pages.
Always use grid
over flex
when implementing a layout.
block
container
image
texts
<div className='bg-white'>
<div className='container grid grid-cols-2 gap-8'>
<div>Image</div>
<div>Texts</div>
</div>
</div>
Requires the warpgate.js
library.
<Money currency='BTC' amount={1.00000000} />
To customize the look, just modify your globals.css
. Here's an example:
/* styles/globals.css */
.money {
@apply space-x-1;
}
.money-currency {
@apply opacity-50;
}
.money-amount {
@apply font-medium;
}
Use this for representing date time from Warpgate API since we don't store timezones in our database.
Requires the warpgate.js
library.
<LocalDate date={new Date()} format='MMMM DD, YYYY' />
<LocalDate date={new Date()} format='fromNow' />
This operation will enable the user to be authenticated given the right credentials. The JWT token is securely stored via http-cookie.
DO NOT store JWT in Local Storage because your app will be vulnerable to XSS attacks.
Requires the warpgate.js
library.
export default apiResponse(req, async () => {
const input = _.pick(req.body, ['username', 'password'])
await login(input)
return {}
})
If you require the user to be authenticated (through HTTP cookies), you need
to wrap your getServerSideProps
with a wrapper.
export const getServerSideProps = requiresUser()
Or if you need to retrieve some data before rendering the page:
export const getServerSideProps = requiresUser(async (ctx, resource) => {
const orders = listOrders({
filter: {
userId: resource.userId
status: ctx.req.query.status || 'pending',
},
})
return {
props: {
orders
}
}
})
Note that getServerSideProps
will be rendered server-side each time the page loads
which means that the page will be slower than usual to load due to not being cached.
Requires the auth.js
library.
If you require an API endpoint to be authenticated:
export default requiresApiUser(async (req, res, resource) => {
const data = await warpgateQuery(QUERY, { userId })
res.json(data)
})
The requiresApiUser
wrapper will return two (2) types of error status codes:
401
if the user isn't authenticated.400
if the callback throws an error.
No need to wrap your callback in a try/catch statement. if the Warpgate API call throws an error, it will be passed on to the response json body.