Tough is a website template for architecture and interior design studios, built on Bootstrap 5, with a full-screen menu and large project photos. The layout is responsive and mobile-ready and works in all popular web browsers. It comes with eight pages: home, about, services, pricing, portfolio, blog, blog post and contact.
The home page has a project slider, counters, services in tabs, a portfolio grid, a client-stories slider and pricing. The inner pages add a team, a “How it works” section, three fee packages, a project grid, a journal with a full post, comments and a sidebar, and a contact page with a working contact form and a map that loads on click. Every page has a “Request a quote” dialog. Tough gives you a ready-made site to present your studio, its projects and its services.
What’s new in 3.0
Bootstrap 5.3.8 (the earlier release used Bootstrap 4.1.0 and jQuery), compiled from Sass with the design’s original proportions, and plain JavaScript with no jQuery. Swiper 14 replaces Owl Carousel on the project slider and the client stories, small built-in modules replace Waypoints, animate.css and the number counter, and the quote dialog uses the browser’s own date and time fields in place of jQuery pickers. Stellar, Scrollax, Magnific Popup, AOS and jQuery Easing, which nothing on the pages used, are gone. Lucide SVG icons replace Open Iconic, Ionicons and two icon fonts, and a subset of Font Awesome 7 Brands draws the social logos, with the X logo in place of the old bird. npm run build (Dart Sass and esbuild) compiles one minified stylesheet and one script.
Lighter pages: all eight pages together went from 18.7 MB and 335 requests to 5.0 MB and 126 requests, and the download from 4.3 MB to 3.5 MB. Every photo has an AVIF version with the JPEG as the fallback, and the full-screen preloader is gone.
No third-party requests: Rubik is self-hosted, the icons are local SVGs, the contact page shows an OpenStreetMap map beside the form that loads only when a visitor clicks “Show map”, and a Google Analytics 4 snippet stays commented out until you add your own ID. Before, every page loaded its font from Google Fonts and the Google Maps script, and the contact page’s map showed only an error panel.
Working forms: the “Request a quote” dialog on every page, the contact form and the blog comment form send through PHP handlers in includes/, each with a spam trap and an in-page message, and the blog search goes to the journal page. Before, none of these forms had field names and none of them posted anywhere.
Accessibility: a skip link, a main landmark and one h1 per page (the home page had five and the inner pages two), the services heading moved out of the tab list, menu buttons that work from the keyboard (Esc closes the full-screen menu and focus returns), names on icon-only links, labelled form fields, visible focus rings and WCAG AA text contrast, with all text at 5.5:1 or better: a darker green for green text, darker body and meta greys, dark text on the green buttons, lighter text on the service tabs and the client-stories panel, and a scrim behind text on photos.
Fixed: the search icon in the blog sidebar shows (it never displayed before), the blog categories are a real list, the About breadcrumb is spelled right, and the “Learn More” and “Get started” buttons and the post, tag, category, comment and pagination links lead to real pages instead of nowhere. Every page has its own title and description.
New demo content: studio copy, four services, named projects, three fee packages, four client stories with their own portraits (they reused the team photos), a team, six journal posts and a full blog post with comments in place of placeholder text, fictional contact details, and credited Unsplash photos for three project images.